Decorators Function in Python

2 minute read

Introduction

In Python, a decorator is a function that takes another function and extends its behavior without explicitly modifying it. Decorators are used to wrap a function, adding functionality to it without changing its original code. Decorators are often used to add cross-cutting concerns to functions, such as logging, caching, authorization, and more.

Basic Syntax

In Python, decorators are denoted by the “@” symbol followed by the name of the decorator function. The decorator function takes a function as an argument and returns a new function that wraps the original function. The new function, called the “wrapper,” adds behavior before and/or after the original function is called. Here’s an example of a basic decorator:

def my_decorator_func(func):
    def wrapper():
        print("Before the {} function is called.".format(func.__name__) )
        func()
        print("After the {} function is called.".format(func.__name__))
    return wrapper

@my_decorator_func
def say_hello():
    print("Hello!")

say_hello()

In this example, the my_decorator_func function is a decorator that takes a function as an argument and returns a new function, wrapper. The new function adds behavior before and after the original function is called. The “@” symbol is used to apply the my_decorator_func decorator to the “say_hello” function.

Real-time Example

Let’s say we have a function that adds two numbers together:

def add_numbers(a, b):
    return a + b

Now let’s say we want to add logging to this function to keep track of when it is called and what its arguments are. We can use a decorator to accomplish this:

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print("Function called: {}".format(func.__name__))
        print("Arguments: {}".format(args))
        print("Keyword arguments: {}".format(kwargs))
        result = func(*args, **kwargs)
        print("Result: {}".format(result))
        return result
    return wrapper

@log_decorator
def add_numbers(a, b):
    return a + b

result = add_numbers(2, 3)
print(result)

In this example, the “log_decorator” function is a decorator that takes a function as an argument and returns a new function, “wrapper.” The new function logs information about the original function’s arguments, result, and when it is called. The “@” symbol is used to apply the “log_decorator” decorator to the “add_numbers” function.

When we call the “add_numbers” function, the decorator is applied and the function is wrapped with the “wrapper” function. The “wrapper” function logs the function’s arguments, calls the original function, logs the result, and returns the result.

The output of running this code will be:

Function called: add_numbers
Arguments: (2, 3)
Keyword arguments: {}
Result: 5
5

As you can see, the decorator added logging behavior to the “add_numbers” function without changing its original code. This makes it easy to extend the functionality of existing functions without having to modify them directly.

Conclusion

Decorators are a powerful feature of Python that allow you to add behavior to functions without modifying their original code. They are used extensively in Python frameworks and libraries, and are a valuable tool for adding cross-cutting concerns to your code.

Updated: