Decorators in Python is very useful concept as it helps in making a function or class more dynamic.
In decorators we have wrapper function(inner function) and we are passing one function as an argument to outer function and which will be called inside wrapped function.

With the help of examples will try to understand how to create a decorator function.

How to create a decorator

In [31]:

""" defining a nested function, in that inner function i.e, a wrapper function is calling the passed function in outer function
"""
def company(decorated_function):
     
    def wrapper_function():
        print('Wrapper function is executed first')
        ## calling the decorator function
        return decorated_function()
    
    return wrapper_function

In [32]:

## creating a decorated function
def new_employee():
    print('Hi! Welcome to Robofied team')
    

In [33]:

## calling a outer function by passsing the created decorated function, 
func = company(new_employee)
func()

Wrapper function is executed first
Hi! Welcome to Robofied team

Another way of calling the decorator function

Syntax of decorator – @ function_name/class_name inside which decorated function will be passed

This syntax is declared before the defintion of the decorated function.

In [34]:

@ company
def new_employee():
    print('Hi! Welcome to Robofied team')

In [35]:

new_employee()

Wrapper function is executed first
Hi! Welcome to Robofied team

Function with agruments

In [36]:

@ company
def office_hours(start_time,finish_time):
    return ('Hi! Your office hours will be ' + str((int(finish_time.split(':')[0]) - int(start_time.split(':')[0])))+ 
              ' hours.')

In [37]:

## Here it is giving the error because our wrapper function will not be able to handle any no.of arguments
office_hours('10:00','18:00')

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-37-c395e695f4e4> in <module>()
----> 1office_hours('10:00','18:00')

TypeError: wrapper_function() takes 0 positional arguments but 2 were given

Redefining the outer function(company in our case) in order to handle the multiple arguments

In [38]:

## Now this nested function will be able to handle any no. of arguments - zero, one , so on arguments and also able to handle 
## key value pair arguments as well.

def company(decorated_function):
    
    ## *args => any no. of aruguments
    ## **kwargs => any no. of key value pair value or dictionary values
    def wrapper_function(*args, **kwargs):
        print('Wrapper function is executed first')
        return decorated_function(*args, **kwargs)
    
    return wrapper_function

In [39]:

## Now this funtction is working fine
@ company
def office_hours(start_time,finish_time):
    return ('Hi! Your office hours will be ' + str((int(finish_time.split(':')[0]) - int(start_time.split(':')[0])))+ 
              ' hours.')

In [40]:

office_hours('10:00','18:00')

Wrapper function is executed first

Out[40]:

'Hi! Your office hours will be 8 hours.'

In [41]:

## This function will also work fine as our function can handle any no. of arguments - zero, one, two etc..
new_employee()

Wrapper function is executed first
Hi! Welcome to Robofied team

As we are doing all the things with function, similarly we can create a decorators using class.
Here, we are not discussing in details using class but it is almost similar as we did for functions.

From the use cases point of view you might be thinking what will be uses of decorators.
Here are some of the use cases where decorators can be used but as we get to know that decorators helps in making any function/class more dynamic is one of the good use case.
Let’s see what are some of the use cases -:
1. Logging
2. Time taken during execution of the function

We will discuss about logging with decorators in upcoming blogs.
Hope you enjoyed learning decorators.Stay tuned for more exciting blogs in intermediate Python. Keep learning!

Leave a Comment

Your email address will not be published. Required fields are marked *