Метод __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__
делает код более гибким и интуитивным, особенно в случаях, где требуется сохранять состояние между вызовами или реализовывать сложную логику.