Summary: In this tutorial, we will learn what is a decorator in Python, what are its different types and how can we use it to modify a function.
Introduction to Decorator
A decorator in Python is any callable object (such as a function) that modifies another existing function or class.
To modify, the decorator accepts the function or class as an argument, wraps it with extra python statements, and returns the same.
In Python, everything is an object, even a function.
Consider the following function for instance:
def add(a, b): return a+b print(add(5, 6)) #output 11
It take two numbers as arguments and returns their addition result.
Although the add method only seems to only return the sum of two numbers, we can further increase its functionality by passing it as an argument to another function:
def add(a, b): return a+b #decorator function that modifies the passed function def my_decorator(func): #wrap the passed funtion with a new function def modified_func(a, b): print("Addition started") print(func(a, b)) print("Addition completed") #return the new function return modified_func #getting the modified version using the decorator function modified_add = my_decorator(add) #executing the function modified_add(5, 6)
In this example, we passed the
add function to the decorator function, defined a new function inside of it, and returned the reference of the new function.
We then get the reference of the new function as
modified_add=my_decorator(add) and invoke the same.
A function defined inside another function is known as the inner function.
Python allows to use decorator in very simple way using a
#decorator function that modifies the passed function def my_decorator(func): #define a new function def modified_func(a, b): print("Addition started") print(func(a, b)) print("Addition completed") #return the new function return modified_func @my_decorator def add(a, b): return a+b add(5, 6)
In this example, we have attached
@my_decorator to the
So, when we call the function as
add(), the new function returned by the specified decorator (i.e. my_decorator) gets invoked instead.
Types of Decorators
As we discussed, the decorator is any callable object that can modify an existing function in Python.
And we know that the instance of a class in Python can also be made callable using the __call__ method.
So in Python, we can create two types of decorators:
- Decorator using function
- Decorator using class
We have already seen the examples of the decorators using function. Let’s see how class decorators work in Python?
To create a decorator using a class, we have to first make its instance callable.
In Python, we can easily do so using the __call__ method.
__call__is a reserved method in Python that when implemented within a class, its instances become callable just like a function (i.e. we can call instances using the ()).
class Connection: def __init__(self, url): self.url = url def __call__(self): print("Connection Opened") print("Acessing URL:", self.url) print("Connection Closed") con = Connection("https://youtu.be/lawHlEbYqcc") con()
Acessing URL: https://youtu.be/lawHlEbYqcc
As you can see that the instance of the
Connection class is callable.
When we call the
con instance using braces, the
__call__ method of the class is invoked.
So now, if we accept the function as a parameter in the
__init__ method of the class and modify it in the
__call__ method, it will behave like a decorator.
class Connection: def __init__(self, func): self.func = func def __call__(self, url): print("Connection Opened") self.func(url) print("Connection Closed") @Connection def downloadFile(url): print("Downloading File:", url) downloadFile("https://youtu.be/lawHlEbYqcc")
Downloading File: https://youtu.be/lawHlEbYqcc
Unlike the function decorator, where we used to define and return an inner function, the
__call__ method here behaves as the modified function.
A decorator is any callable object that can modify an existing class or function in Python.
In Python, we can create a decorator either by using a class or by using a function.
The @ symbol in Python eliminates writing boilerplate code to implement a decorator on a function.