Как можно создать декоратор с аргументами?

Чтобы создать декоратор с аргументами в Python, нужно обернуть основную функцию-декоратор в еще одну функцию. Эта внешняя функция принимает аргументы для декоратора и возвращает саму функцию-декоратор, которая затем принимает и декорирует исходную функцию.

  def decorator_with_args(arg1, arg2):
      def actual_decorator(func):
          def wrapper(*args, **kwargs):
              print(f"Аргументы декоратора: {arg1}, {arg2}")
              # Дополнительная логика до вызова функции
              result = func(*args, **kwargs)
              # Дополнительная логика после вызова функции
              return result
          return wrapper
      return actual_decorator

  @decorator_with_args("значение1", "значение2")
  def my_function():
      print("Функция выполняется")

  my_function()
  

Декоратор с аргументами - это функция, которая возвращает декоратор. Это позволяет передавать параметры в декоратор при его применении.

Вот пример реализации:


 def decorator_with_arguments(argument1, argument2):
  def actual_decorator(func):
   def wrapper(*args, **kwargs):
    print(f"Декоратор вызван с аргументами: {argument1}, {argument2}")
    print(f"Выполняется функция: {func.__name__}")
    # Здесь можно выполнить любую дополнительную логику, используя argument1 и argument2

    result = func(*args, **kwargs)  # Вызываем исходную функцию

    print(f"Функция {func.__name__} завершила выполнение")
    return result
   return wrapper
  return actual_decorator

 # Пример использования
 @decorator_with_arguments("Hello", "World")
 def my_function(x, y):
  print(f"Функция my_function вызвана с аргументами: {x}, {y}")
  return x + y

 result = my_function(5, 10)
 print(f"Результат: {result}")

 # Альтернативный способ применения (без @ синтаксиса):
 # my_function = decorator_with_arguments("Hello", "World")(my_function)
 

Разберем по частям:

  • decorator_with_arguments(argument1, argument2): Это внешняя функция, которая принимает аргументы, предназначенные для конфигурации декоратора. Она возвращает actual_decorator.
  • actual_decorator(func): Эта функция принимает декорируемую функцию func в качестве аргумента и возвращает wrapper. Это стандартный декоратор.
  • wrapper(*args, **kwargs): Это обертка, которая выполняется при каждом вызове декорируемой функции. Здесь можно добавить логику до и после вызова исходной функции.
  • func(*args, **kwargs): Это вызов исходной функции с переданными ей аргументами.

Объяснение работы:

  1. Когда мы используем @decorator_with_arguments("Hello", "World") перед определением функции my_function, Python сначала вызывает decorator_with_arguments("Hello", "World"). Эта функция возвращает actual_decorator.
  2. Затем actual_decorator вызывается с my_function в качестве аргумента. actual_decorator возвращает wrapper.
  3. В результате, my_function заменяется на wrapper.
  4. Когда мы вызываем my_function(5, 10), на самом деле вызывается wrapper(5, 10). wrapper выполняет свою логику (например, печатает аргументы), вызывает исходную my_function(5, 10) и возвращает результат.

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

  • Гибкость: Можно настраивать поведение декоратора в зависимости от переданных аргументов.
  • Переиспользование: Можно создать один декоратор, который будет выполнять разные действия в зависимости от конфигурации.
  • Чистота кода: Улучшается читаемость и организация кода, так как логика, связанная с декорированием, вынесена в отдельную функцию.

Примеры использования:

  • Логирование: Декоратор, который логирует вызовы функций с возможностью указать уровень логирования и файл для записи.
  • Кэширование: Декоратор, который кэширует результаты функций с возможностью указать время жизни кэша.
  • Авторизация: Декоратор, который проверяет права доступа пользователя перед выполнением функции.
0