Как с помощью декораторов можно отслеживать количество вызовов функции?

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

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

Пример реализации:


import functools

def call_counter(func):
    """Декоратор, отслеживающий количество вызовов функции."""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        wrapper.calls += 1
        return func(*args, **kwargs)
    wrapper.calls = 0
    return wrapper

@call_counter
def my_function(x):
    """Пример функции, которую нужно отслеживать."""
    return x * 2

print(my_function(5))  # Output: 10
print(my_function(10)) # Output: 20
print(f"Функция my_function была вызвана {my_function.calls} раз(а).") # Output: Функция my_function была вызвана 2 раз(а).
  

Разъяснение кода:

  • call_counter(func): Это функция-декоратор. Она принимает функцию func в качестве аргумента.
  • @functools.wraps(func): Этот декоратор из модуля functools сохраняет метаданные исходной функции (имя, docstring и т.д.). Это важно для правильной работы introspection и отладки.
  • wrapper(*args, **kwargs): Это функция-обертка, которая заменяет исходную функцию. Она принимает произвольное количество позиционных и именованных аргументов, чтобы можно было применять декоратор к любой функции.
  • wrapper.calls += 1: При каждом вызове wrapper, счетчик wrapper.calls увеличивается на 1.
  • return func(*args, **kwargs): Вызывает исходную функцию с переданными аргументами и возвращает результат.
  • wrapper.calls = 0: Инициализирует атрибут calls у функции-обертки wrapper нулем. Этот атрибут будет хранить количество вызовов.
  • @call_counter: Применение декоратора call_counter к функции my_function.

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

  • Чистота кода: Отделение логики отслеживания вызовов от основной логики функции.
  • Повторное использование: Декоратор можно применять к любой функции, не меняя её код.
  • Читаемость: Код становится более читаемым и понятным.
0