Декораторы — это мощный и полезный инструмент в Python, позволяющий изменять поведение функции без изменения ее кода. Они реализованы с использованием специального синтаксиса, начиная с символа @, за которым следует имя функции-декоратора.

Чтобы создать декоратор, вы определяете функцию, которая принимает другую функцию в качестве аргумента и возвращает модифицированную версию этой функции.

Например, вот простой декоратор, добавляющий два к результату функции:

def add_two(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result + 2
    return wrapper

Чтобы использовать этот декоратор, вы можете применить его к любой функции, используя символ @, за которым следует имя декоратора:

@add_two
def calculate(x, y):
    return x + y

result = calculate(3, 4)
print(result)  # prints 9

В этом примере функция calculate заключена в функцию wrapper, определенную в декораторе add_two. Когда вызывается функция calculate, вместо нее выполняется функция wrapper, которая вызывает исходную функцию calculate и добавляет два к ее результату.

Декораторы часто используются для добавления функциональности к существующей функции без изменения ее кода. Например, вы можете использовать декоратор для регистрации аргументов и возвращаемого значения функции или для кэширования результатов функции для повышения ее производительности.

Важно отметить, что декораторы применяются в том порядке, в котором они появляются. Например:

def add_two(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result + 2
    return wrapper

def multiply_by_three(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result * 3
    return wrapper

@add_two
@multiply_by_three
def calculate(x, y):
    return x + y

result = calculate(3, 4)
print(result)  # prints 23

В этом случае функция calculate сначала декорируется декоратором multiply_by_three, а затем декоратором add_two. Это означает, что сначала применяется функция wrapper, определенная в декораторе multiply_by_three, а затем функция wrapper, определенная в декораторе add_two.

Декораторы — это мощный инструмент, который можно использовать для краткого и элегантного изменения поведения функций. Они обычно используются в Python для добавления функциональности к существующему коду без изменения его реализации.

Декораторы также могут быть полезны для изменения поведения методов класса. Например, вы можете использовать декоратор, чтобы добавить функцию ведения журнала ко всем методам в классе:

def log_methods(cls):
    for name, value in vars(cls).items():
        if callable(value):
            setattr(cls, name, log_method(value))
    return cls
def log_method(func):
    def wrapper(*args, **kwargs):
        print(f"Calling method {func.__name__} with args {args} and kwargs {kwargs}")
        result = func(*args, **kwargs)
        print(f"Method {func.__name__} returned {result}")
        return result
    return wrapper

@log_methods
class MyClass:
    def method1(self, x):
        return x * 2
    
    def method2(self, x, y):
        return x + y

obj = MyClass()
obj.method1(10)
obj.method2(5, 6)
Output:
Calling method method1 with args (<__main__.MyClass object at 0x0000024E0439E910>, 10) and kwargs {}
Method method1 returned 20
Calling method method2 with args (<__main__.MyClass object at 0x0000024E0439E910>, 5, 6) and kwargs {}
Method method2 returned 11

В этом примере декоратор log_methods применяет декоратор log_method ко всем функциям в классе.