Decorators
You'll learn to
- -Explain what a decorator is: a function that wraps another function
- -Apply a decorator with `@decorator_name` syntax
- -Build a simple timing or logging decorator from scratch
A decorator is a function that takes another function as input and returns a new function that wraps it, typically adding behavior before and/or after the original runs, without modifying the original function's own code. This directly builds on the closures chapter from the Functions module: a decorator is a closure whose remembered enclosing variable happens to be the function it is wrapping.
Building a Decorator by Hand
Before the @ syntax, look at what a decorator actually is: a function that accepts a function and returns a new function.
Notice wrapper takes *args, **kwargs, exactly the accept-anything tool from the earlier functions module, so log_calls can wrap a function with any signature at all, not just ones that take two arguments.
The @decorator Syntax
@decorator_name placed directly above a function definition is exactly equivalent to the manual reassignment above: def add(...): ... followed by add = log_calls(add), just cleaner to read.
A Timing Decorator
Another classic, genuinely useful decorator measures how long a function takes to run, using the time module.
Foreshadowing: Caching Is Just a Decorator
Here is the payoff for everything in this chapter and the closures chapter before it. What if, instead of timing a function, a wrapper checked whether it had already computed the result for these exact arguments, and returned the cached answer instead of recomputing it?
This is exactly what memoization is: a cache, keyed by arguments, wrapped around a function that would otherwise repeat expensive work. The Algorithms phase of this course covers memoization for recursive algorithms in depth, and Python's own functools.lru_cache gives you this decorator for free, but the underlying mechanism is precisely the closure-plus-wrapper pattern you just built by hand.
- -A decorator is a function that takes a function and returns a new (usually wrapping) function.
- -@decorator_name above a def is sugar for func = decorator_name(func).
- -A wrapper almost always accepts *args, **kwargs so it can wrap functions of any signature.
- -A caching decorator is a closure holding a dict, checked and updated on every call. This is memoization, which the next phase of this course (Algorithms) builds on directly.
Interview Signal is part of Pro
See a real weak answer next to a real strong one for this exact topic.
Quiz is part of Pro
Test what you just read with a short quiz, and bank the XP.
Module Assignment is part of Pro
Write real, graded Python for this module - right here in the course.
Discussion0
Join the Discussion
Sign in to leave comments, reply to others, or like insights.
No comments yet. Be the first to start the thread!