Decorators in Python

A guide to understanding decorators, their use and importance in Python

Jayashree domala
4 min readOct 17, 2020

Decorators as the name suggests have the work of decorating. In Python, they allow you to decorate a function.

Suppose you have a function with does some basic job. Now you want to add more functionalities to it. So you can either add the extra code to the old function or create a brand new function that contains the old code and add the new code to it. The problem with the former is that you won’t be able to call the old function and the problem with the latter is that you have to re-create the entire function.

Maybe if there was a switch function to quickly add the functionality and delete it, then the work would be easier.

So Python has decorators that allow you to attach extra functionality to an already existing function. The @ operator is used and placed on top of the original function.

So we start off by creating a simple function and call it.

>>> def func1():
return 'python'
>>> func1()
'python'

Now if I just run”func1" it will tell me it’s a function.

>>> func1
<function __main__.func1()>

Now assigning the function to the variable and calling it.

>>> param1 = func1()>>> param1
'python'

Now if I assign the function without the parenthesis as below and call it, then ‘python’ will be returned as the output. So the question is if ‘lang’ pointing out to func1 or has made a copy of it. We can check this by deleting the original function and realize that lang() still gives the output as it is still pointing to the original function object. It is important to know that functions are objects that cannot be passed into other objects.

>>> lang = func1>>> lang()
'python'
>>> del func1>>> lang()
'python'

Now let’s create another function and define other functions inside it.

>>> def hello(name='Jay'):
print("This is a hello function, which is executed")
def greet():
return "\t This is greet() function inside hello"
def bye():
return "\t This is bye() function inside hello"
print(greet())
print(bye())
print("End of hello function")
>>> hello()
This is a hello function, which is executed
This is greet() function inside hello
This is bye() function inside hello
End of hello function

Now if we try to execute the greet() and welcome() function separately, it would give an error since their scope is limited to the hello() function only.

>>> greet()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-22-db845682bfe7> in <module>
----> 1 greet()
NameError: name 'greet' is not defined

So what we will do is make the hello() func return these functions. And then assign a variable while calling the function. So the functions will be returned and stored in the variable which can be used.

>>> def hello(name='Jay'):
print("This is a hello function, which is executed")
def greet():
return "\t This is greet() function inside hello"
def bye():
return "\t This is bye() function inside hello"
print("Returning function")
if name == 'Jay':
return greet
else:
return bye
>>> func1 = hello()
This is a hello function, which is executed
Returning function
>>> func1()
'\t This is greet() function inside hello'
>>> print(func1())
This is greet() function inside hello

Now this concept will be used for building a decorator. We will create 2 functions and pass one function as an argument in another function.

>>> def color():
return 'Blue'
>>> def shape(func):
print('Shape function runs')
print(func())
>>> shape(color)
Shape function runs
Blue

Creating a decorator

Here we create a main function that takes in as argument another function. Inside this main function, another function is defined and in this, the argument function is called which is decorated with two print functions above and below and hence decorators, the name.

>>> def new_deco(original_func):
def greet():
print("Hello")
original_func()
print("Bye")
return greet

Now we create a function which needs the decoration.

>>> def func_needing_deco():
print("I need decoration")

Now we will call the decorator and pass the function which needs decoration.

>>> decorated_func = new_deco(func_needing_deco)>>> decorated_func()
Hello
I need decoration
Bye

Now, this process was too long. So we can use @ operator and add the decorator to the function which requires it. So the function below the @ operator gets passed to the decorator function.

>>> @new_deco
def func_needing_deco():
print("I need decoration")
>>> func_needing_deco()
Hello
I need decoration
Bye

In case now you don't need the decoration, you can comment it.

>>> # @new_deco
def func_needing_deco():
print("I need decoration")
>>> func_needing_deco()
I need decoration

Refer to the notebook here.

Beginner-level books to refer to learn Python:

Advance-level books to refer to learn Python:

Reach out to me: LinkedIn

Check out my other work: GitHub

--

--

Jayashree domala
Jayashree domala

Written by Jayashree domala

Self-driven woman who wishes to deliver creative and engaging ideas and solutions in the field of technology.

No responses yet