Python Decorators
Python Decorators
Decorators are a powerful feature in Python that allows you to modify the behavior of functions or classes without changing their source code.
Basic Decorator Pattern
A decorator is simply a function that takes another function as an argument and returns a modified version of it.
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before function call")
result = func(*args, **kwargs)
print("After function call")
return result
return wrapper
@my_decorator
def say_hello(name):
print(f"Hello, {name}!")
# Usage
say_hello("World")
Common Use Cases
1. Timing Functions
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.4f} seconds")
return result
return wrapper
2. Caching/Memoization
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
3. Authentication
def require_auth(func):
def wrapper(user, *args, **kwargs):
if not user.is_authenticated:
raise PermissionError("Authentication required")
return func(user, *args, **kwargs)
return wrapper
Decorators with Arguments
To create decorators that accept arguments, you need an extra layer of nesting:
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet():
print("Hello!")
Best Practices
<p>Always use <code>functools.wraps</code> to preserve the original function's metadata.</p>
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper