How do I make function decorators and chain them together?

Function decorators allow you to wrap a function in another function. This can be useful for adding additional behavior to a function, such as logging, timing, or counting how many times a function has been called.

To create a function decorator in Python, you need to define a function that takes another function as an argument, and then defines a new function that wraps the original function and adds the additional behavior that you want. You can then use the @ symbol followed by the name of the decorator function to apply the decorator to the original function.

Watch a course Python - The Practical Guide

Here's an example of a simple function decorator that logs the arguments and return value of a function:

def log(func):
    def wrapper(*args, **kwargs):
        print(f'Calling {func.__name__} with arguments {args} and keyword arguments {kwargs}')
        result = func(*args, **kwargs)
        print(f'{func.__name__} returned {result}')
        return result
    return wrapper

To use this decorator, you would apply it to a function like this:

def log(func):
    def wrapper(*args, **kwargs):
        print(f'Calling {func.__name__} with arguments {args} and keyword arguments {kwargs}')
        result = func(*args, **kwargs)
        print(f'{func.__name__} returned {result}')
        return result
    return wrapper

@log
def add(x, y):
    return x + y

Now, every time you call the add function, it will be logged by the decorator.

You can chain multiple decorators together by applying them one after the other. For example:

@log
@timer
def add(x, y):
    return x + y

This will apply both the log decorator and the timer decorator to the add function. The timer decorator could be another function that adds timing behavior to the decorated function, for example.

Decorators are applied in the order that they are listed, so in this case the log decorator will be applied first, and then the timer decorator will be applied to the resulting decorated function.