Decorators
- Write decorators that wrap functions with new behavior
- Preserve function metadata with
functools.wraps - Understand decorator syntax as sugar for higher-order functions
- Chain multiple decorators on a single function
Flask's @app.route, pytest's @pytest.fixture, and functools.lru_cache are all decorators — the pattern powers every routing, DI, and caching layer in modern Python. Senior engineers write parameterized decorators with functools.wraps to preserve introspection for logging and OpenAPI generation.
- Skipping
@functools.wraps(func)— breaks__name__,__doc__, and framework introspection like FastAPI's schema builder. - Confusing
@decoand@deco(...)— a parameterized decorator needs three nested functions, not two. - Decorating methods without handling
self— bound-method semantics differ; test on classes, not just free functions.
A decorator is just a function that takes a function and returns a (usually wrapped) function.
The anatomy
@timed # syntactic sugar for: fib = timed(fib)
def fib(n): ...
@wraps(fn) from functools preserves the original function's name and docstring on the wrapper.
Common uses
- Logging / timing
- Caching (
@functools.lru_cache) - Authentication checks
- Retry logic
Try it
- Add an
@functools.lru_cache(maxsize=None)above@timedand watchfib(30)get instant. - Write a
@retry(times=3)decorator factory that retries on exceptions.
3 graded exercises
Write the code, click Check. We’ll tell you exactly what to fix.
- Exercise 1
Write a decorator
shoutingthat wraps any function returning a string and returns the same string uppercased. Apply it to a functiongreet(name)that returns"hello, " + name. Printgreet("Ada")— expected:HELLO, ADA. - Exercise 2
Write a decorator
count_callsthat adds a.callscounter to the function. Apply it todef hit(): pass. Callhit()three times, then printhit.calls— expected:3. - Exercise 3
Use
functools.lru_cacheto memoize a recursive Fibonacci functionfib(n). Printfib(30)— expected:832040. It should compute in well under a second (unlike the naive recursive version).