Starting with a Clean Slate

A Straight-forward example:

What do you do before eating a chocolate🍫? Well you don’t chug it without removing the wrapper do you? So before you eat the chocolate, you remove the wrapper.

Removing a wrapper is a MUST function before eating the chocolate.

The idea of decorators is pretty much the same. You must perform a certain function before performing another function

Lets represent the above idea into code

# decorator function
def remove_wrapper(func):
    def fx():
        print("wrapper_removed")
        func()
    return fx
  
# main function to perform
def eat_chocolate():
    print("Eating🍴")
    
remove_wrapper(eat_chocolate)()
# wrapper_removed
# eating chocolate

Here the remove_wrapper() function takes a function as an argument, wraps the argument into a certain function and returns the function. In our case, fx() is wrapping the func() here, remove_wrapper() is the decorator since it has a function as an argument.

The @ symbol

Instead of calling the decorator function with a function argument, we can use the @ symbol to simplify and make the decorator function much more reusable.  We can omit the above code from line 7 with this code.

@remove_wrapper
def eat_chocolate():
    print("eating chocolate")

@remove_wrapper
def eat_cookies():
    print("Eating Cookies")

eat_chocolate()
eat_cookies()
wrapper_removed
eating chocolate
wrapper_removed
Eating Cookies

Here, whenever we call out eat_chocolate() function, the remove_wrapper() function is automatically called before evaluating the actual eat_chocolate() function. The decorator also becomes much more reusable when we use the @ symbol.

Moving a step forward

A decorator is a function returning another function which lets users add behaviours into certain parts of code without actually modifying the code. This definition clearly applies in our examples given below and above.

A function with parameters

Above examples consisted only the functions which took no arguments but to make functions support arguments when using decorators, we use the concept of *args and **kwargs in python.

*args

  • Allows us to pass a variable number of non-keyword arguments to a Python function..

**kwargs

  • allow you to pass multiple values to a function with a named keyword. **kwargs can then be evaluated as a dictionary inside a function.
def remove_wrapper(func):
    def fx(*args, **kwargs):
        print("wrapper_removed")
        func(*args, **kwargs)  
    return fx

@remove_wrapper
def eat_chocolate(chocolate, size, caloric_content):
    print(f"Eating🍴 {chocolate}, {size}, weight : {caloric_content.get('weight')}")


eat_chocolate('dairymilk😋', 'familypack', {
              'weight': '60gm', 'total_calorie': 250})

wrapper_removed
Eating🍴 dairymilk😋, familypack, weight : 60gm

Here, we pass the chocolate, size and caloric_content of the chocolate. chocolate and size are passed as arguments whereas the caloric_content is a dictionary which is received as **kwargs (keyword arguments) 

We can also chain multiple decorators to a single function. We just stack one decorator on top of another. The order of the stack matters since the topmost decorator is evaluated first. Here is an example.

def remove_wrapper(func):
    def fx(*args, **kwargs):
        print("wrapper_removed")
        func(*args, **kwargs)
    return fx

def buy_chocolate(func):
    def fx(*args, **kwargs):
        print("Chocolate Bought")
        func(*args,**kwargs)
    return fx

@buy_chocolate
@remove_wrapper
def eat_chocolate(chocolate):
    print(
        f"Eating🍴 {chocolate}")


eat_chocolate('dairymilk😋')
Chocolate Bought
wrapper_removed
Eating🍴 dairymilk😋

Summary🫡

Python decorators modify the behavior of functions or classes without directly changing their code. They wrap or decorate a function or class with extra functionality using the “@” symbol placed above the definition. Decorators add features like logging, input validation, timing, or authentication to functions or classes. They help separate concerns, promote code reusability, and enhance your code’s functionality.

Websites use a decorator to restrict certain parts of the website. Like a membership portal where users cannot enter without paying

Leave a Reply

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