A decorator in Python is a function that takes another function as an argument and extends its behavior without explicitly modifying it. It is one of the most powerful features of Python. It has several usages in the real world like logging, debugging, authentication, measuring execution time, and many more. Show
Scope of Article
IntroductionSuppose you have a set of functions and you only want authenticated users to access them. Therefore, you need to check whether a user is authenticated or not before proceeding with the rest of the code in the function. One way to do this is by calling a separate function inside all the functions and using conditional statements. But this will require us to change the code for each function. A better solution here would be to use a Decorator. A Decorator is just a function that takes another function as an argument and extends its behavior without explicitly modifying it. This means that a decorator adds new functionality to a function. By the end of this article, you will understand what does "extending a function without actually modifying it" means. Prerequisites for Learning DecoratorsTo understand decorators in Python, you must have an understanding of the following concepts:
Don't worry! We will go through these things in the next section. If you are already familiar, feel free to skip. Takeaway:
Functions in PythonA function returns a value based on the given arguments. For instance, the following function returns twice of a number:
Higher-order function is a function that takes a function as an argument or returns a function. Inner FunctionsWe can define a function inside other functions. Such functions are called inner functions or nested functions. Decorators in Python also use inner functions. For example, the following is a function with two inner functions:
Note đ: The inner functions are locally scoped to the parent. They are not available outside of the parent function. If you try calling the first_child outside of the parent body, you will get a NameError. Inner functions can access variables in the outer scope of the enclosing function. This pattern is known as a Closure. Consider the following example:
Takeaway:
Introduction to DecoratorsNow that we have the pre-requisite knowledge for understanding decorators, let's go on to learn about Python decorators. As discussed before, a decorator in Python is used to modify the behavior of a function without actually changing it. Syntax: where func is the function being decorated and decorator is the function used to decorate it. Let's see an example to understand what does this mean:
The most important line in the code is this: 0 Takeaway:
Syntactic DecoratorThe above decorator pattern got popular in the Python community but it was a little inelegant. We have to write the function name thrice and the decoration gets a bit hidden below the function definition. Therefore, Python introduced a new way to use decorators by providing syntactic sugar with the @ symbol. Syntax: 1 Takeaway:
Preserving the Original Name and Docstring of the Decorated FunctionIn Python, functions have a name attribute and a docstring to help with debugging and documentation. See the following example (we are using the same decorator created before): 4 Takeaway:
Reusing DecoratorA decorator is just a regular Python function. Hence, we can reuse it to decorate multiple functions. Let's create a file called decorators.py with the following code: 8 Takeaway:
Decorators Functions with ParametersWhat if the function we are decorating has some parameters? Let's try it with an example: 0 Takeaway:
Returning Values from Decorated FunctionsWhat happens to the returned value from the decorated function? Let's check out with an example. Consider the following add function, it prints a statement then returns the sum of the two numbers, we are decorating it with the previously created do_twice decorator: 4 Takeaway:
Decorators with ArgumentsYou can pass arguments to the decorator itself! Let's see what does this means with code to better understand it. Previously, we created a decorator called do_twice. Now, we will extend it to repeat any number of times. Let's call this new decorator repeat. 8
0
1
2 Takeaway:
Chaining DecoratorsChaining the decorators means that we can apply multiple decorators to a single function. These are also called nesting decorators. Consider the following two decorators: 5
Now, we will use both the decorators on a single function by stacking them like this: 6 Takeaway:
Fancy DecoratorsYou need a basic understanding of classes in Python for this section. I recommend going through the Class in Python article on Scaler Topics if you are unfamiliar with classes. Till now, you have seen how to use decorators on functions. You can also use decorators with classes, these are known as fancy decorators in Python. There are two possible ways for doing this:
Decorating the Methods of a ClassPython provides the following built-in decorators to use with the methods of a class:
Let's see an example of all the three decorators: 9 Takeaway:
Classes as DecoratorsWe can also use a class as a decorator. Classes are the best option to store the state of some data, so let's understand how to implement a stateful decorator with a class that will record the number of calls made for a function. There are two requirements to make a class as a decorator:
Also note that we use functools.update_wrapper instead of functools.wraps in case of a class as a decorator. Now, let's implement the class: 2 Takeaway:
Real-World Usage of DecoratorsOne real-world usage of decorators in Python is to measure the execution time of a function. 5 |