Theme: Decorators are metaprogramming tools that modify or enhance functions. They rely heavily on closures to maintain state.
| Topic | Key insight |
|---|---|
| Import Time | Decorators execute exactly when the module is imported. |
| Closures | Functions that remember the state of the environment where they were created. |
nonlocal |
Required if a closure needs to reassign a free variable. |
@functools.wraps |
Copies __name__ and __doc__ from the decorated function to the wrapper. |
@lru_cache |
Memoizes function calls. Drastically speeds up recursive algorithms. |
@singledispatch |
Provides elegant function overloading based on the first argument's type. |
examples.py— Import execution, closures,nonlocal, and the standard library decorators.exercises.py— Exercises building an accumulator, a retry mechanism, and access control.mini_project.py— A parameterized rate-limiting API decorator using sliding windows.benchmarks.py— Proves the significant performance gains of@lru_cachevs recursive overhead.notes.md— Scope rules, UnboundLocalError, and decorator factory construction.pitfalls.md— Losing metadata without@wraps, and the mutable closure trap.interview_questions.md— L3 to L6 interview prep.architecture_notes.md— CPython'sLOAD_DEREFbytecode and__closure__cells.
# Rule 1: Always use @functools.wraps
def my_decorator(func):
@functools.wraps(func) # <--- NEVER FORGET THIS
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
# Rule 2: Use nonlocal to mutate free variables
def counter():
count = 0
def inc():
nonlocal count # <--- Required for reassignment
count += 1
return count
return inc
# Rule 3: Don't write giant if/elif type checks; use @singledispatchReference: Fluent Python 2nd ed., Chapter 9 — pages 339–380