Decorators in Python
Decorator modifies the functionality of another function.
Now, suppose you want to add more functionality to a function, what you will do ?
You will add more coding and will modify the old code and return something or you can create a new function containing old as well as new code.
What if I want to remove that extra functionality ?
You have to delete the part of code or a newly created function and also have to make sure that function is not getting called .
We have better way for this and this is where Decorators come in. Decorators help you to add more functionality to a function. @ operator is used on the top of original function.
adding extra functionality to a function:
@any_decorator
def func():
#code part
any_decorator is an extra functionality for function func() and we can easily add extra functionality and to remove that extra functionality, simply remove the @any_decorator line at the top of func().
Before going for Decorators, let’s see some concepts:
functions within functions
def hello(n):
print("Hello",n)
def name():
print('Inside name function...')
name() #calling name function
print('Inside hello function...')
hello("Jose")Output:
Hello Jose
Inside name function...
Inside hello function...
Here, name() function is inside the hello() function.
returning the functions
def hello(n):
print("Hello",n)
def name():
return 'Inside name function...'
return name
x=hello("Jose")
print(x) Output:Hello Jose
<function hello.<locals>.name at 0x7f7d3e8c22f0>
Look here, how x is pointing to a inside function, name() . To print, use x() as shown below:
def hello(n):
print("Hello",n)
def name():
return 'Inside name function...'
return name
x=hello("Jose")
print(x())Output:Hello Jose
Inside name function...
functions as arguments
def hello():
print("Hello")def name(func):
func()
print("Jose")
name(hello)Output:
Hello
Jose
Here, we have passed hello() function as an argument to a name() function and calling the hello function to print the statement.
Let’s create a Decorator:
def some_decorator(func): def name_func():
print("before executing the func...") func()
print("after executing the func...")
return name_func
def need_a_decorator():
print("This function need a Decorator to add functionality...")
Let’s call need_a_decorator() function:
need_a_decorator()Output:
This function need a Decorator to add functionality...
I want to add the functionality to the need_a_decorator function. We can pass this function as an argument to a some_decorator() function.
need_a_decorator = some_decorator(need_a_decorator)
need_a_decorator()Output:
before executing the func...
This function need a Decorator to add functionality...
after executing the func...
What happened here ? we have added the functionality to need_a_decorator() function using some_decorator() function by passing it as an argument.
Let’s see how we can rewrite this using @ symbol i.e. Decorator:
@some_decorator
def need_a_decorator():
print("This function need a Decorator to add functionality...")need_a_decorator()Output:
before executing the func...
This function need a Decorator to add functionality...
after executing the func...
Full code here :
def some_decorator(func):def name_func():
print("before executing the func...")func()print("after executing the func...")return name_func@some_decorator
def need_a_decorator():
print("This function need a Decorator to add functionality...")need_a_decorator()Output:
before executing the func...
This function need a Decorator to add functionality...
after executing the func...
That’s it!