Метод __call__ в Python позволяет объекту класса вести себя как функция. Если класс реализует этот метод, его экземпляры можно вызывать, как если бы они были функциями. Это делает объекты класса вызываемыми (callable), что открывает возможности для создания функциональных объектов с состоянием.
Когда объект вызывается как функция (например, obj()), Python автоматически вызывает метод __call__ этого объекта. Это позволяет объектам сохранять состояние между вызовами и выполнять сложную логику.
class Adder:
def __init__(self, initial_value=0):
self.value = initial_value
def __call__(self, x):
self.value += x
return self.value
adder = Adder(10) # Создаем объект с начальным значением 10
print(adder(5)) # Вывод: 15 (10 + 5)
print(adder(3)) # Вывод: 18 (15 + 3)
Здесь:
Adder инициализируется с начальным значением initial_value.__call__ принимает аргумент x и добавляет его к текущему значению value.adder вызывается как функция, и каждый вызов изменяет его внутреннее состояние.__call__ делает код более интуитивным, особенно когда объект представляет собой действие или операцию.class Cache:
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
if args in self.cache:
return self.cache[args]
result = self.func(*args)
self.cache[args] = result
return result
@Cache
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(10)) # Вывод: 55
print(fibonacci(20)) # Вывод: 6765
Здесь:
Cache реализует кэширующий декоратор.__call__ проверяет, есть ли результат для данных аргументов в кэше, и возвращает его. Если нет, вычисляет результат и сохраняет его в кэше.fibonacci использует этот декоратор для оптимизации вычислений.class Timer:
def __enter__(self):
import time
self.start_time = time.time()
def __exit__(self, exc_type, exc_val, exc_tb):
import time
print(f"Время выполнения: {time.time() - self.start_time} секунд")
def __call__(self, func):
def wrapper(*args, **kwargs):
with self:
return func(*args, **kwargs)
return wrapper
@Timer()
def long_running_function():
import time
time.sleep(2)
long_running_function() # Вывод: Время выполнения: ```2.0 секунд
Здесь:
Timer реализует контекстный менеджер и метод __call__, что позволяет использовать его как декоратор.@Timer() измеряет время выполнения функции long_running_function.Метод __call__ позволяет объектам класса вести себя как функции. Это полезно для:
Использование __call__ делает код более гибким и интуитивным, особенно в случаях, где требуется сохранять состояние между вызовами или реализовывать сложную логику.