Decorators
Guidance
- Use functools.wraps to preserve the original function signature and metadata.
- Keep decorator layers shallow and readable.
- Prefer class-based decorators when you need state or extra methods.
Bad Example
import random
import time
def timer(wrapped):
"""Decorator that prints execution time."""
def decorated(*args, **kwargs):
start = time.time()
ret = wrapped(*args, **kwargs)
print("execution took: {} seconds".format(time.time() - start))
return ret
return decorated
@timer
def random_sleep():
"""Sleep for a short random time."""
time.sleep(random.random())
Good Example
import functools
import time
def timer(wrapped):
"""Decorator that prints execution time."""
@functools.wraps(wrapped)
def decorated(*args, **kwargs):
start = time.time()
ret = wrapped(*args, **kwargs)
print("execution took: {} seconds".format(time.time() - start))
return ret
return decorated