Как декоратор используется с функцией?

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

Он применяется с помощью символа @ над определением функции, которую нужно декорировать.

Пример:

@my_decorator
def my_function():
    print("Hello!")
  
Это эквивалентно my_function = my_decorator(my_function).

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

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

Синтаксис: Синтаксически декоратор обозначается символом @, расположенным непосредственно перед определением функции, которую нужно декорировать. Имя, следующее за @, - это имя функции-декоратора.

Пример:


def my_decorator(func):
    def wrapper():
        print("До выполнения функции.")
        func()
        print("После выполнения функции.")
    return wrapper

@my_decorator
def say_hello():
    print("Привет!")

say_hello()
    

Разъяснение примера:

  • my_decorator - это функция-декоратор. Она принимает функцию func в качестве аргумента.
  • wrapper - это внутренняя функция, определенная внутри декоратора. Она содержит дополнительную логику (вывод текста до и после выполнения).
  • Внутри wrapper вызывается исходная функция func().
  • Декоратор my_decorator возвращает функцию wrapper.
  • Строка @my_decorator перед определением say_hello эквивалентна say_hello = my_decorator(say_hello). То есть, функция say_hello передается в декоратор my_decorator, который возвращает новую, "обернутую" функцию, которая присваивается переменной say_hello.
  • Когда мы вызываем say_hello(), на самом деле вызывается wrapper(), которая выводит "До выполнения функции.", затем вызывает исходную say_hello() (выводит "Привет!"), а затем выводит "После выполнения функции.".

Декораторы с аргументами: Если функция, которую нужно декорировать, принимает аргументы, их нужно передать в wrapper, используя *args и **kwargs:


def my_decorator_with_args(func):
    def wrapper(*args, **kwargs):
        print("До выполнения функции с аргументами.")
        result = func(*args, **kwargs)
        print("После выполнения функции с аргументами.")
        return result
    return wrapper

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

result = add(5, 3)
print(result)
    

Преимущества использования декораторов:

  • Улучшение читаемости кода: Декораторы позволяют отделить логику, касающуюся конкретной задачи, от логики, касающейся общих операций (логирование, аутентификация и т.д.).
  • Повторное использование кода: Один и тот же декоратор можно применять к нескольким функциям.
  • Избежание дублирования кода: Логика, которую нужно применить к нескольким функциям, определяется в одном месте (в декораторе).
  • Более чистый и структурированный код: Декораторы позволяют сделать код более модульным и организованным.
0