Python Decorators

    In this tutorial, we will discuss Python Decorator and understand its usages. We will also learn how decorators related to user-defined functions.

    What are decorators in Python?

    Decorators are the special syntax used in python which used above the function to increase the functionality of that function by wrapping it around by another function. Like function in python, Decorators are of two type built-in decorator and user-defined decorators. Decorators as by its name itself, it is a special syntax used to decorate the other functions.

    Point to remember

    • Before we further discuss Python, decorators keep in mind that Python is an Object-Oriented Programming language and everything in it is an object even the user-defined function.
    • The same function can be associated with the different name or identifier, for e.g.
    def hello(string):
        print(string)   
    hello("Hello")
    bonjour= hello #  here function name has become a variable
    bonjour("Hello")   # here bonjour and hello are function name or identifier.
    • The function name can be passed as an argument.
    • We cannot directly access the nested function from the global scope of the program, for that, we have to return the nested function using its outer function.
    • In Python closure, we return the nested function name (not complete function, just name) using the outer function.

    Using Decorator

    As we know that Decorators are used to increasing the functionality of a function. To define a decorator, we use ‘@’ symbol and the decorator name, here decorator name could be a function name which has a nested function. The function we want to decorate, just one line above it we use the decorator symbol and decorator name.

    Example:

    def  new_decorator(main_func):        
        def wrap_func():
            print("******************************")
            main_func()
            print("*********************************")
            print("Thank Q for Decorating me!")
        return wrap_func
    
    @new_decorator
    def need_decorator():
        print("I want to decorate")
    
    need_decorator()
    ######_____________________The Above Code Is Equivalent __________________######
    
    def  new_decorator(main_func):
        def wrap_func():
            print("******************************")
            main_func()
            print("*********************************")
            print("Thank Q for Decorating me!")
        return wrap_func
    
    
    def need_decorator():
        print("I want to decorate")
    
    decorated = new_decorator(need_decorator)
    decorated()

    Output:

    ******************************
    I want to decorate
    *********************************
    Thank Q for Decorating me!

    Behind the code

    We have provided two codes one is for the decorator using the @ symbol and the other one is simple using function assignments. Both coding patterns are known as decorator. Always remember put the decorator name after the @ symbol and one line above the function on which you want to decorate. The Equivalate code we have provided is very easy to understand the inner working of a decorator.

    Chaining Decorator

    In the above example, we have only used one decorator to decorate the main function now we  will use more than one decorator on a function.

    Example:

    def s(main_func):
        def decorate_with_star():
            print("*" * 30)
            main_func()
            print("*" * 30)
        return decorate_with_star
    
    def b(main_func):
    
        def decorate_with_dollor():
            print("$" * 30)
            main_func()
            print("$" * 30)
        return decorate_with_dollor
    
    @s
    @b
    def decorate():
        print("Hello")
    
    decorate()

    Output:

    ​​​​​​​ ****************************** $$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Hello $$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ******************************