What is a decorator in Python?
A decorator is a function that wraps another function to add behaviour before or after it runs applied with the @ syntax.
Python
Overview
A decorator is a callable that takes a function, wraps it with extra behaviour, and returns the new wrapper. The `@decorator` syntax is shorthand for `func = decorator(func)`. Decorators are used for logging, authentication, caching, timing, and more.
Key Points
- •`@decorator` above a function is syntactic sugar for `func = decorator(func)`.
- •The wrapper function should accept `*args, **kwargs` and call the original function.
- •Use `functools.wraps(func)` to preserve the original function's name and docstring.
- •Decorators can be stacked they are applied bottom-up.
- •Class decorators and decorators with arguments follow the same pattern but add extra layers.
Examples
Simple timing decorator
pythonimport time
import functools
def timer(func):
@functools.wraps(func) # preserves func.__name__ and __doc__
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
print(f"{func.__name__} took {elapsed:.4f}s")
return result
return wrapper
@timer
def slow_function():
time.sleep(0.1)
slow_function() # prints: slow_function took 0.1001sDecorator with arguments
pythondef repeat(times):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in range(times):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # prints 3 timesStacking decorators (applied bottom-up)
python@require_auth # applied second
@timer # applied first
def dashboard():
...
# equivalent to: dashboard = require_auth(timer(dashboard))Pro Tip
Always use `@functools.wraps(func)` inside your wrapper. Without it, `func.__name__` and `func.__doc__` are replaced by the wrapper's which breaks introspection, logging, and some testing tools.