How do decorators work in Python and how do I write them?
· Category: Python Programming
Short answer
A decorator is a function that takes another function as input and returns a new function (or callable) that adds behavior before or after the original. Use @decorator_name syntax to apply them.
Steps
- Write a wrapper function that accepts the original function.
- Define an inner function that calls the original and adds extra logic.
- Return the inner function.
- Apply with
@my_decoratorabove the function definition.
from functools import wraps
import time
def timer(func):
@wraps(func)
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)
return "done"
slow_function()
Tips
- Always use
@wraps(func)fromfunctoolsto preserve the original function's metadata. - Decorators can accept arguments by adding an outer factory function.
- Classes can implement
__call__to act as decorators.
# Parameterized decorator
def repeat(n):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet():
print("Hello")
greet()
Common issues
- Forgetting
@wrapscauses the decorated function to lose its name and docstring. - Decorators that do not return the wrapper result break the function's return value.
- Decorating methods requires careful handling of
self; consider using descriptor-based decorators for classes.