📘 Lesson 22 · Advanced

Python Decorators

Write decorators, use @functools.wraps, pass arguments to decorators, with examples.

What is a Decorator?

A decorator is a function that wraps another function to add behaviour before or after it runs, without modifying the original code. It's used for logging, timing, authentication, and caching — cross-cutting concerns you want to apply consistently. The @name syntax is just clean shorthand for func = decorator(func).

basic.py
def log_call(func):
    def wrapper(*args, **kwargs):
        print(f"→ Calling {func.__name__}")
        result = func(*args, **kwargs)
        print(f"← Finished")
        return result
    return wrapper

@log_call
def add(a, b): return a + b

print(add(3, 7))
▶ Output
→ Calling add
← Finished
10

Timing Decorator with @functools.wraps

Without @functools.wraps(func), the wrapped function loses its original name and docstring. Always include it — it preserves the original function's metadata so tools and introspection still work correctly.

timer.py
import time, functools

def timer(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        print(f"{func.__name__} took {time.perf_counter()-start:.4f}s")
        return result
    return wrapper

@timer
def big_sum():
    return sum(range(1_000_000))

big_sum()
▶ Output
big_sum took 0.0301s

Decorator with Arguments

To pass arguments to a decorator, add a third level of nesting: the outer function takes the argument, returns a decorator, which wraps the function.

repeat.py
def repeat(n):
    def decorator(func):
        def wrapper(*a, **kw):
            for _ in range(n): func(*a, **kw)
        return wrapper
    return decorator

@repeat(3)
def say_hi(): print("Hi!")

say_hi()
▶ Output
Hi!
Hi!
Hi!
Python's standard library includes useful built-in decorators: @property, @classmethod, @staticmethod, and @functools.lru_cache.

🧠 Quick Check

What does @functools.wraps(func) preserve?

Speed
Name and docstring
Return value
Arguments

Tags

decorators@decoratorfunctoolswrapshigher-order functionswrappertiming