You can also nest Decorators. This means that you can use a decorator to decorate another decorator. You can do this by just stacking the Decorators on top of each other.

For example, let’s say that we have a decorator that will print the time it took for a function to execute and another decorator that will execute a function multiple times. We can do it like this:

from functools import wraps
from time import time
 
def timer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time()
        result = func(*args, **kwargs)
        end = time()
        print(f'Time elapsed: {end - start}')
        return result
    return wrapper
 
def repeat(n=1):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for _ in range(n):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator
 
@timer
@repeat(n=3)
def func():
    print('Hello World!')

Now, if we call func(), it will print Hello World! 3 times and it will print the time it took for it to execute.

But if we had used the Decorators in the opposite order, like this:

@repeat(n=3)
@timer
def func():
    print('Hello World!')

Then it would have printed Hello World! 3 times, but it would have printed the time it took for it to execute three times as well (once for each time it was executed).