__call__ 是一个特殊方法(也称为魔术方法),用于使一个类的实例能够像函数一样被调用。当定义了这个方法后,实例对象可以后接括号(即 ())来触发调用,这会让实例表现得像函数一样。
- 使实例可调用:允许类的实例像函数一样被调用。
 - 保持状态:可以在多次调用之间保持实例的状态(因为实例可以存储属性)。
 - 实现装饰器:常用于实现装饰器类(Decorator Class)。
 - 模拟函数行为:让对象具备函数的行为,同时保留类的特性(如属性、方法)。
 
基本语法
class MyClass:def __call__(self, *args, **kwargs):# 定义调用时的行为return "Called with:", args, kwargsobj = MyClass()
result = obj(1, 2, 3, name="Alice")  # 触发 __call__
# result = obj()  # 触发 __call__
print(result)# ('Called with:', (1, 2, 3), {'name': 'Alice'})
# ('Called with:', (), {}) 
输出:
('Called with:', (1, 2, 3), {'name': 'Alice'}) 
关键特点
-  
**
*args和**kwargs**
__call__可以接受任意数量的位置参数和关键字参数,类似于普通函数。 -  
实例本身仍然是一个对象
即使定义了__call__,实例仍然可以拥有属性和方法:class Adder:def __init__(self, initial=0):self.total = initialdef __call__(self, x):self.total += xreturn self.totaladd = Adder(10) print(add(5)) # 15(10 + 5) print(add(3)) # 18(15 + 3) -  
用于装饰器
__call__可以让类的实例作为装饰器使用:class Logger:def __init__(self, func):self.func = funcdef __call__(self, *args, **kwargs):print(f"Calling {self.func.__name__}")return self.func(*args, **kwargs)@Logger def greet(name):return f"Hello, {name}!"print(greet("Alice"))输出:
Calling greet Hello, Alice! 
**__call__ vs __init__**
 
| 方法 | 调用时机 | 用途 | 
|---|---|---|
__init__ | 实例化时调用(obj = MyClass()) | 初始化对象属性 | 
__call__ | 实例被调用时(obj()) | 让实例像函数一样执行 | 
实际应用场景
-  
状态保持的函数(类似闭包)
class Counter:def __init__(self):self.count = 0def __call__(self):self.count += 1return self.countcounter = Counter() print(counter()) # 1 print(counter()) # 2 -  
实现策略模式
class Multiply:def __call__(self, a, b):return a * bclass Add:def __call__(self, a, b):return a + bdef calculate(operation, a, b):return operation(a, b)print(calculate(Multiply(), 3, 4)) # 12 print(calculate(Add(), 3, 4)) # 7 -  
动态生成对象行为
class Power:def __init__(self, exponent):self.exponent = exponentdef __call__(self, x):return x ** self.exponentsquare = Power(2) cube = Power(3) print(square(4)) # 16 print(cube(3)) # 27 
总结
__call__让类的实例可以像函数一样被调用。- 适用于需要保持状态的函数、装饰器类、策略模式等场景。
 - 不同于 
__init__,它控制的是实例的调用行为,而非初始化行为。 
如果你想让一个对象既能存储数据又能像函数一样执行操作,__call__ 是一个非常有用的工具!