Decorators in Python

In this class, we discuss Decorators in Python.

For Complete YouTube Video: Click Here

Decorators

The reader should have prior knowledge of functions as parameters and returning functions. Click here.

Before going to the concept of decorators, take an example related to decorators and understand.

def my_decorator(func):
    def inner(x,y):
        if x+y >10:
            func(x,y)
        else:
            print("values are less than ten")
    return inner
def f(x,y):
    z=x+y
    print(z)
f=my_decorator(f)
f(6,6)

Output
12

In the above example, we have written two functions, f and my_decorator.

Function f is taking two parameters, x and y.

The functionality of function f is adding the values of variables x and y.

Suppose we want to change the functionality of function f. without changing the code of function f.

we use another function, my_decorator to apply a condition on function f, without changing the functionality of function f.

In the my_decorator function, we have an inner function called inner.

The my_decorator function is returning the inner function.

f=my_decorator(f). In this code line, we call the function my_decorator, and function f is passed as an argument.

my_decorator is returning the reference of the inner function. So variable f is referencing the inner function.

Take the statement f(6,6). Here f means the inner function is called.

Note:

variable f is referencing to inner function, and Inner function has access to func variable from my_decorator. Func is referencing function f.

The above note is critical to understand. Analyze as much as possible.

The logic in the inner function. If x+y greater than ten. Then call the function func. Function func is referencing function f.

If the condition not satisfied, display x+y less than ten.

What condition did we impose on function f without changing the code of function f?

If x+y value greater than ten, then call the function f. otherwise, display x+y less than ten.

We can impose the same condition in the function f. But why we did separately?

Decorator: A decorator is a function that imposes a condition on other functions without changing other functions’ functionality.

The same logic of decorator we applied in the above example.

What is the use of a decorator?

Suppose we want to impose a condition on some function f. we write a decorator.

If you want to impose another condition on the function f., you write a different decorator.

The example shown below how to define a decorator.

def my_decorator(func):
    def wrapper(x,y):
        if x+y >10:
            func(x,y)
        else:
            print("values are less than ten")
    return wrapper
@my_decorator
def f(x,y):
    z=x+y
    print(z)
#f=my_decorator(f)
f(6,6)

Output:
12

Chaining of Decorators

Take an example and understand the concept of chaining of decorators.

def decor1(func):  
    def inner1():  
        x = func()  
        return x * x  
    return inner1  
  
def decor(func):  
    def inner():  
        x = func()  
        return 2 * x  
    return inner  
  

def num():  
    return 10
num=decor1(decor(num))
  
print(num())  

Output:
400

If we want to apply two different conditions on a function f. we use the concept of chaining of decorators.

In the above example, function num is given.

the statement num=decor1(decor(num))

decor(num) calls the function decor, and the function num is passed as an argument.

The function decor is returning function inner. And the function inner is calling function num using variable func.

Function inner is passed as an argument to function decor1.

Function decor1 is returning the reference of function inner1. And the variable func in function decor1 is referencing function inner.

Reference of function inner1 is given to the variable num.

Execution:

The statement print(num()). when ever function num() is called.

Inner1 function is called. And inside the inner1 function, func1 is called.

func1 is referencing to function inner. And inner is called, and the function inner is referencing to function num.

Function num return value ten. And the value is taken by function inner and the function inner return value 20.

The value 20 is taken by function inner1 and return the value 400.

The final output is 400.

The example to call the chaining of decorators is given below.

def decor1(func):  
    def inner():  
        x = func()  
        return x * x  
    return inner  
  
def decor(func):  
    def inner():  
        x = func()  
        return 2 * x  
    return inner  
  
@decor1
@decor
def num():  
    return 10
  
print(num())

Output:
400

Analyze the program given below for better practice

def decor1(func):  
    def inner1(z):  
        x = func(z)  
        return x * x  
    return inner1  
  
def decor(func):  
    def inner(y):  
        x = func(y)  
        return 2 * x  
    return inner  
  
@decor1
@decor
def num(y):  
    return 10+y
  
print(num(1))

Output
484