Monday, November 30, 2020

Python Decorators

The Python language provides a simple yet powerful syntax called ‘decorators’. A decorator is a function or a class that wraps (or decorates) a function or a method. The ‘decorated’ function or method will replace the original ‘undecorated’ function or method. Because functions are first-class objects in Python, this can be done ‘manually’, but using the @decorator syntax is clearer and thus preferred.


def foo():

    # do something


def decorator(func):

    # manipulate func

    return func


foo = decorator(foo)  # Manually decorate


@decorator

def bar():

    # Do something

# bar() is decorated


This mechanism is useful for separating concerns and avoiding external unrelated logic ‘polluting’ the core logic of the function or method. A good example of a piece of functionality that is better handled with decoration is memoization or caching: you want to store the results of an expensive function in a table and use them directly instead of recomputing them when they have already been computed. This is clearly not part of the function logic.



Decorators are very powerful and useful tool in Python since it allows programmers to modify the behavior of function or class. Decorators allow us to wrap another function in order to extend the behavior of wrapped function, without permanently modifying it.



Decorator seems to be very useful when doing some kind of profiling 


# importing libraries 

import time 

import math 

  

# decorator to calculate duration 

# taken by any function. 

def calculate_time(func): 

      

    # added arguments inside the inner1, 

    # if function takes any arguments, 

    # can be added like this. 

    def inner1(*args, **kwargs): 

  

        # storing time before function execution 

        begin = time.time() 

          

        func(*args, **kwargs) 

  

        # storing time after function execution 

        end = time.time() 

        print("Total time taken in : ", func.__name__, end - begin) 

  

    return inner1 

  

  

  

# this can be added to any function present, 

# in this case to calculate a factorial 

@calculate_time

def factorial(num): 

  

    # sleep 2 seconds because it takes very less time 

    # so that you can see the actual difference 

    time.sleep(2) 

    print(math.factorial(num)) 

  

# calling the function. 

factorial(10) 

Output:


3628800

Total time taken in :  factorial 2.0061802864074707





References:

https://docs.python-guide.org/writing/structure/#the-actual-module

https://www.geeksforgeeks.org/decorators-in-python/


No comments:

Post a Comment