A decorator is a design pattern tool in Python for wrapping code around functions or classes (defined blocks). This design pattern allows a programmer to add new functionality to existing functions or classes without modifying the existing structure. The section provides an overview of what decorators are, how to decorate functions and classes, and what problem can it solve.
A decorator is a function that takes another function as an argument, does some actions, and then returns the argument based on the actions performed. Since functions are first-class object in Python, they can be passed as arguments to another functions.
Hence we can say that a decorator is a callable that accepts and returns a callable.
Below code shows a simple decorator that add additional notes to the my_function docstring:
Help on function my_function in module __main__: my_function(string1) Return the string. Hi George, Im a simple Decorator.
From the above explanation, you can understand how to decorate a function. But it is unacceptable to define a function, assign it to a variable, then reassign the decorated function to the same variable. Hence Python 2.5 introduced a syntax for decorating function by prepending an
@ character with the decorator name and adding directly above the function declaration. Below code shows how to use the syntax:
Here we use @ character for decorating function.
The above code is syntactically equivalent to the following code
In this case, the reverse_decorator function executes and creates the reference for revserse_wrapper. Let’s look into the below example for better understanding:
Inside reverse_decorator function
Here the reverse_decorator does not execute the function reverse_wrapper instead it creates the reference and returns it when the callable invokes the function.
Inside reverse_decorator function
<function reverse_decorator..reverse_wrapper at 0x0000015762A16708>
Inside reverse_wrapper function
Single Function and Multiple Decorator
Now you are clear about how to use the @syntax to decorate a function. Another cool stuff is that we can use multiple decorators on a single function. One important thing to note here is the order of the decorator applied is important, which is applied from bottom to top. Let’s look into multiple decorators.
Here the string is reversed first and foremost, and secondarily it converts to uppercase.
The above code is syntactically equivalent to
Arguments in Decorator Function
So far, you have seen decorators without any arguments. In certain cases, it’s necessary to pass arguments to decorate the method accordingly.
Arguments accepted are: Travelling, Reading
My Hobbies are Travelling and Reading
In the above case, the decorator will not take any arguments instead it is passed to the wrapper function by the callable. The below code provides more clarity in the process of passing the arguments using reference.
<function decorator_arguments..wrapper_arguments at 0x7f100315e158>
Arguments accepted are: Travelling, Reading
Where Decorators are Used?
The standard library provides many modules that include decorators and many Python tools and frameworks that make use of decorators. Few examples are:
- You can use @classmethod or @staticmethod decorator for creating a method without creating an instance
- The mock module permits the use of @mock.patch or @mock.patch.object as a decorator which is used for unit testing.
- Common tools such as Django (uses @login_required) for setting login privileges and Flask (uses @app.route) for function registry uses decorators.
- To identify a function as an asynchronous task Celery uses @task decorator.
Why you should write Decorators
Two important reasons to write this reusable piece of Python functionality are when written properly the decorators are modular and explicit.
- Modularity of Decorators
- Decorators are Explicit
Modularity of Decorators
Using decorators’ programmers can add or remove functionalities easily in defined blocks of code, which refrains the repetition of boilerplate setup.
Decorators are explicit
Programmers can apply Decorators to all callable based on the need. This ensures readability and provides clean code.
Here we will discuss a few decorator use-cases which help you to understand When to write Decorators.
- Functional Addons
- Data Sanitization
- Function Registration
The first and foremost reason to write a decorator is its flexibility to add extra functionality to the defined blocks of code(functions and classes).
With proper data sanitization methods, you can remove or destroy the data that is stored on memory and make it impossible to recover it. For example, you may use the facility of cache to avoid running the same function or you may use methods to validate the user login credentials and so on, which points to the importance of data sanitization. A decorator can properly sanitize the arguments that passed to the decorated function and also sanitize the data returned from the function.
Another point to write a decorator is to register a function. Here decorator allows two or more subsystems to communicate without having much information about each other.
The above section shows how decorators help in decorating functions. We have seen that decorators are callable that accepts and returns a callable. Since classes are callable, decorators are also used to decorate classes. Some of the uses of decorating classes are:
- Addition or enhancement of attributes
- Attribute interaction
- Alter the API of a class (alter the way of declaring classes and its instance use)
Let’s go through how to decorate a function using class.
Inside Function Call GeeksforGeeks
Let’s look into an another example. Below code, sort the instance based on their creation time. Here we require three additional attributes- the instantiation timestamp, __lt__ and __gt__ methods.
[Python, Data Analysis, Machine Learning]
new_init, its primary responsibility is to run the wrapped function and also add an extra functionality to the wrapped function. The
@functools.wraps(org_init) update the wrapper function to reflect the look of wrapped function. Check functools for detail understanding.
Decorate a Function and return a Class
Sometimes it’s necessary to decorate a function and return a class. Say, for example, advanced cases developers can subclass a class in an API. It can also avoid an increase in boilerplate code.
Hi George, Im here to help you with addition! 2 4 7
Here the decorator creates a subclass of Addition and returns the instance of the subclass rather than reference (
And the __call__ method in the class `Addition` means that its instance is callable. Hence the instance of subclass `AddSubclass()` can run the task and as a result the programmer can avoid calling the run method as
Decorators are an excellent tool for wrapping code around functions and classes, which provides an efficient way to use boilerplate code and also contributes to readability. Even though they are modular and explicit, there are drawbacks to this tool. Since it’s a tool for wrapping code around defined blocks, debugging becomes more challenging. And also, poorly written decorators may result in an error.
After all, a well-written decorator can be treated as an efficient reusable piece of Python functionality for wrapping defined blocks of code.
Attention geek! Strengthen your foundations with the Python Programming Foundation Course and learn the basics.
To begin with, your interview preparations Enhance your Data Structures concepts with the Python DS Course.
- How to Become a Data Analyst in 2019: A Complete Guide
- How to Become a Data Scientist in 2019: A Complete Guide
- Function Decorators in Python | Set 1 (Introduction)
- Decorators in Python
- Decorators with parameters in Python
- Memoization using decorators in Python
- Useful cases to illustrate Decorators in python
- Nested Decorators in Python
- Chain Multiple Decorators in Python
- Conditional Decorators in Python
- Debugging decorators in Python
- Error Handling in Python using Decorators
- How to preserve Function Metadata while using Decorators?
- PEP 8 : Coding Style guide in Python
- Guide to Install MongoDB with Python | Windows
- The Ultimate Guide to Data Classes in Python 3.7
- How To Use Jupyter Notebook - An Ultimate Guide
- Tableau Installation Guide
- Guide to deploy containers on Google Cloud Run
- Guide to install TuriCreate in Python3.x
If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to email@example.com. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.