Зачем нужен метод __call__ и что значит «вызвать объект как функцию»?
Встретил в чужом коде obj() — то есть вызывают сам экземпляр, как будто это функция. Видел, что для этого есть __call__. В каких случаях это реально полезно, а не выпендрёж?
3 ответа
__call__ делает экземпляр вызываемым: после его определения obj() запускает этот метод. Полезно, когда объекту нужно хранить состояние между вызовами, но при этом вести себя как функция. Классический пример — счётчик или конфигурируемая функция:
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, x):
return x * self.factor
double = Multiplier(2)
print(double(5)) # 10
Здесь double — объект, но используется как функция. Это удобнее замыкания, когда настроек много. Реальные применения: декораторы-классы, функции потерь в ML (хранят гиперпараметры), кэширующие обёртки. Кстати, обычные функции в Python — тоже объекты с __call__, поэтому f() и работает.
Когда нужна «функция с памятью/настройками». Объект помнит состояние, а вызывается как функция. Альтернатива замыканиям, но читается понятнее когда параметров много.
Чтобы понтоваться. Всё то же делается обычной функцией.