Decorators Deep Dive
Explore how Python decorators extend and modify function behavior efficiently using the @ syntax. Understand general-purpose decorators, metadata preservation with functools.wraps, and practical applications like timing and input validation. Gain skills to write modular, clear, and maintainable Python code.
In the previous lesson, we saw how a function’s behavior can be extended by wrapping it inside another function. While effective, manually reassigning a function (such as my_func = wrapper(my_func)) is verbose, error-prone, and obscures the relationship between the original function and its enhancement. The modification appears disconnected from the function’s definition.
Python addresses this limitation through decorators. A decorator is a syntactic construct that allows us to apply a wrapper to a function at the moment it is defined. By placing a decorator above a function using the @decorator_name syntax, we declaratively specify that the function’s behavior should be augmented.
This approach improves clarity and maintainability. Decorators, therefore, enable cleaner separation of concerns and promote more modular program design.
The @ syntax
A decorator is simply a function that takes another function as input and returns a new function. In the last lesson, we applied this transformation manually. Python’s @ syntax provides syntactic sugar that performs this reassignment automatically when the function is defined.
Let's look at the difference.
Lines 1–5: We define the
my_decoratorutility. Its job is to manufacture a new function (wrapper) that injects a print statement before running whatever function is passed to it (func).Lines 7–8: We define
say_hellonormally. At this stage,say_hellois just a simple function that prints"Hello!".Line 11: ...