Common Mistakes & Gotchas with Decorators
Decorators are powerful, but beginners often make mistakes that lead to confusing errors. Let’s look at the most common pitfalls and how to avoid them.
1. Forgetting to Return the Wrapper
A decorator must return the wrapper function. If you forget the return, the decorated function becomes None.
def bad_decorator(func):
def wrapper(*args, **kwargs):
print("Doing something...")
func(*args, **kwargs)
# Missing "return wrapper" here!
@bad_decorator
def greet(name):
print(f"Hello, {name}!")
print(greet) # Output: None 😢
2. Losing Function Metadata
Without @wraps, the decorated function loses its original name and docstring.
This is problematic for debugging and documentation tools.
def my_decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@my_decorator
def greet():
"""This function says hello."""
print("Hello!")
print(greet.__name__) # wrapper ❌
print(greet.__doc__) # None ❌
Fix: Use functools.wraps(func) to preserve metadata.
3. Over-Decorating Functions
Applying too many decorators can make code hard to read and debug. Keep decorators focused on one responsibility.
@decorator_one
@decorator_two
@decorator_three
def some_function():
pass
✔️ Keep it simple. Chain only when necessary.
4. Forgetting Arguments
If your function requires arguments but your wrapper doesn’t accept them, you’ll get an error.
def my_decorator(func):
def wrapper(): # ❌ Forgot *args, **kwargs
print("Before...")
func() # ❌ This will fail if arguments exist
return wrapper
@my_decorator
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # TypeError ❌
Fix: Always include *args and **kwargs in the wrapper.
5. Decorators Running Too Early
Remember that decorators are executed at function definition time, not when the function is called.
def announce(func):
print("Decorator is running!") # Runs immediately
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@announce
def greet():
print("Hello!")
# Output when script runs:
# Decorator is running! ✅
This can surprise beginners. It’s normal behavior.
Summary
- Always return the wrapper from your decorator.
- Use
functools.wrapsto keep function name and docstring. - Don’t overuse decorators — keep them clean and focused.
- Always handle
*argsand**kwargsproperly. - Remember decorators execute at definition time, not runtime.
No comments:
Post a Comment