🕯️ Magic Note
Decorators are functions that take another function as input and return a new function. The @decorator_name syntax is just sugar for function = decorator_name(function). Python applies the decorator at definition time, not at call time.
- Decorators are applied at definition time, not runtime
- Multiple decorators stack: @timer @log def func() applies from bottom to top
- Decorators can accept arguments with nested functions
- Common uses: @staticmethod, @classmethod, @property, @cache
| Decorator | Purpose | Example |
|---|---|---|
| @staticmethod | Method without self | Inside classes |
| @classmethod | Method receives class | Alternative constructors |
| @property | Method acts as attribute | Computed values |
| @lru_cache | Cache repeated calls | Expensive computations |
| @timer | Measure execution time | Performance debugging |
Python
# Creating a simple timing decorator
import time
def logtime(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f”⏱ {end – start:.3f}s”)
return result
return wrapper
Python
# Using the @logtime decorator
@logtime
def brew():
print(“brewing…”)
time.sleep(0.002)
brew()
# Output: brewing…
# Output: ⏱ 0.002s
Python
# Multiple decorators stacking
@logtime
@authenticate
def secret_spell():
return “✨”
# authenticate runs first on the way in
# logtime wraps everything including authenticate
- Forgetting that decorators run at definition time, causing confusion about print statements appearing at import
- Stacking decorators in the wrong order, thinking they run from top to bottom when they wrap from bottom to top
- Not using @functools.wraps inside custom decorators, losing the original function’s metadata for debugging
⚡ Whisper
The at sign is not just decoration. It is a gate. Your function enters. Magic happens around it. The function emerges unchanged but surrounded by power. This is the symbol of transformation without touch.