Nearby lessons
116 of 159Python - Decorators
- Understand what a decorator function is
- Extend the functionality of an existing function without modifying it
- Use the @decorator syntax
- Call a function with and without a decorator
- Apply multiple decorators using decorator chaining
What is a Decorator?
A Decorator is a function which can take a function as an argument, extend its functionality, and return a modified function with the extended functionality.
The main objective of decorator functions is to extend the functionality of existing functions without modifying those functions.
The Problem
Consider the following function:
Explanation
This function always prints the same output for any name:
The Requirement
Now we want to modify this function so that it provides a different message when the name is Sunny.
We can do this without touching the wish() function by using a decorator.
Example: A Decorator for the wish() Function
Explanation
decoris a decorator function. It takesfuncas an argument and returnsinner.inner()checks whether the name isSunny. If it is, it prints a different message; otherwise it calls the originalfunc(name).@decorabovewishtells Python to passwishthroughdecor. Wheneverwish()is called, the extended version executes automatically.
The Inner Function Pattern
Notice the structure of a typical decorator:
Explanation
The decorator decor takes the original function func as input, defines an inner function that adds the extra behaviour, and returns inner.
From that point onwards, calling the original function name executes the inner function instead.
How to Call the Same Function With and Without a Decorator
If we do not use the @decor syntax, the decorator is not applied automatically.
In that case we can manually pass the function to the decorator to obtain the extended version.
Explanation
wish("Durga")andwish("Sunny")call the original function directly, so the decorator is not executed.decorfunction = decor(wish)manually creates the extended version.decorfunction("Durga")anddecorfunction("Sunny")call the extended version, so the decorator is executed.
Example 2: smart_division
This decorator prevents a ZeroDivisionError when dividing by zero.
Explanation
Without the decorator, division(20, 0) would raise a ZeroDivisionError.
With the @smart_division decorator, the inner() function checks whether b is 0 before calling the original division(), so the program never crashes.
Decorator Chaining
We can define multiple decorators for the same function. All these decorators together form Decorator Chaining.
How Chaining Works
When multiple decorators are applied, the decorator closest to the function works first, and then the outer decorator works on its result.
In the example above, decor is applied first, then decor1 is applied to the result.
Example: Decorator Chaining with num()
Explanation
The decor decorator runs first: it calls num(), gets 10, and returns 2 * 10 = 20.
Then decor1 runs on that result: it calls the already-decorated function, gets 20, and returns 20 * 20 = 400.
Therefore, the final output is 400.
Demo Program for Decorator Chaining
Explanation
The output confirms the order of chaining:
decor1(the outer decorator) starts first.- It calls the
decor-wrapped function, which prints the first message. - Finally the original
wish()body executes.
- A decorator is a function that takes a function as an argument and returns an extended version of it
- The @decorator syntax automatically passes the function below it to the decorator
- A decorator typically defines an inner function that adds extra behaviour
- Calling the original function name after decoration executes the extended version
- Multiple decorators on one function form a decorator chain; the inner decorator works first