课程 · 12 · 01 / 12
Decorators Mastery: From Closures to Class Decorators
Master Python decorators from the ground up. Understand closures, build function and class decorators, use functools, and apply real-world patterns.
TIPLearning Objectives: After this lesson, you'll understand closures deeply, build function and class decorators from scratch, use functools effectively, and apply real-world decorator patterns in production code.
How Decorators Transform Functions
Before diving into code, let's visualize what decorators actually do. A decorator wraps a function, adding behavior before and/or after the original function runs.
When you write @timer above a function, Python replaces that function with the wrapped version. The original function still exists—it's just called from inside the wrapper.
The Foundation: Understanding Closures
TIP🧠 See it before reading the math: open Python Tutor and paste a counter-factory like
def make_counter():\n count = 0\n def increment():\n nonlocal count\n count += 1\n return count\n return increment\n\nc = make_counter()\nc(); c(); c(). The arrows pointing fromincrementback into the closed-overcountcell make closures finally feel concrete.
Before diving into decorators, we need to solidify our understanding of closures—the mechanism that makes decorators work.
What is a Closure?
A closure is a function that remembers values from its enclosing scope even after that scope has finished executing. Let's visualize how scope works:
Interact with the visualizer above to see how variables are captured in different scopes. Now let's see closures in action:
Visualizing Closure Memory
Closures capture variables by reference, not by value. This visualization shows how multiple closures can share the same memory cell:
Function Decorators: The Basics
A decorator is simply a function that takes a function as input and returns a new function. Let's trace through the execution:
The Call Stack During Decoration
Use the call stack visualizer above to understand how function calls nest. Now let's see the actual decorator pattern:
The Manual Way
The @ Syntax
The @decorator syntax is just syntactic sugar. Here's how stacked decorators work:
Preserving Function Metadata with functools
Decorators with Arguments
Creating decorators that accept arguments requires an extra level of nesting. Let's visualize this three-layer structure:
Class-Based Decorators
Decorators can also be implemented as classes using __call__.
Decorating Classes
Decorators can also modify classes, not just functions.
Real-World Decorator Patterns
Authentication and Authorization
Caching and Memoization
Input Validation
Advanced: Decorators That Work on Methods and Functions
Practice Exercises
Exercise 1: Rate Limiter Decorator
Exercise 2: Deprecation Warning Decorator
Key Takeaways
| Concept | Description |
|---|---|
| Closures | Functions that capture and remember variables from enclosing scope |
@wraps | Preserves original function's metadata when decorating |
| Decorator arguments | Require factory function that returns the actual decorator |
| Class decorators | Use __call__ to make instances callable |
| Method decorators | Need careful handling of self parameter |
lru_cache | Built-in memoization with LRU eviction |
Common Decorator Patterns
- Logging/Tracing - Track function calls and results
- Timing - Measure execution time
- Caching - Store results for repeated calls
- Retry - Automatically retry on failure
- Validation - Check inputs before execution
- Authentication - Verify access permissions
- Rate limiting - Control call frequency
Next Steps
In the next lesson, we'll explore Generators and Iterators—learn the iterator protocol, build generators with yield, understand lazy evaluation, and see how generators relate to coroutines and async programming.
Ready to master lazy evaluation? Generators await in the next lesson!
Further Reading
Visualize It
- Python Tutor — paste a decorator with closure capture and step through. The "wait, the inner function remembers
func?" moment lands instantly.
Official Docs
- PEP 318 — Decorators for Functions and Methods — the proposal that introduced
@decoratorsyntax. functoolsmodule —wraps,lru_cache,cache,singledispatch,partial,reduce. The decorator standard library.contextlib.ContextDecorator— write something once, use it as bothwithblock AND@decorator.
Tutorials
- Real Python — Primer on Python Decorators — the canonical 30-min walkthrough.
- Dan Bader — Closures in Python — short, practical.
Production Patterns
tenacity— the modern retry decorator (@retry(stop=stop_after_attempt(3))).backoff— exponential-backoff retry decorator.functools.cacheandfunctools.lru_cache— memoization in two characters.@dataclass— the most-used decorator in modern Python.
Books
- Book: Fluent Python (2nd ed.) — Chapter 9 ("Decorators and Closures"). The definitive treatment.
- Book: Effective Python — Items 26–27 cover
@functools.wrapsand decorator composition.