在 Python 中,__call__
是一个特殊的魔术方法(magic method),它允许一个类的实例像函数一样被调用。当你在一个对象后面加上 ()
并执行时(例如 obj()
),Python 会自动调用该对象的 __call__
方法。
1. __call__
的基本用法
(1)定义 __call__
方法
class CallableClass:
def __init__(self, name):
self.name = name
def __call__(self, *args, **kwargs):
print(f"对象 {self.name} 被调用,参数: args={args}, kwargs={kwargs}")
# 实例化
obj = CallableClass("MyCallable")
# 调用对象,触发 __call__
obj(1, 2, 3, a=4, b=5)
输出:
对象 MyCallable 被调用,参数: args=(1, 2, 3), kwargs={'a': 4, 'b': 5}
(2)__call__
的作用
- 让对象可以像函数一样被调用。
- 适用于需要 保持状态 的“函数”(例如装饰器、闭包替代方案)。
2. __call__
的调用机制
当你执行 obj(*args, **kwargs)
时,Python 内部会转换为:
obj.__call__(*args, **kwargs)
即:
obj(1, 2, 3) # 等价于 obj.__call__(1, 2, 3)
3. 实际应用场景
(1)实现装饰器(Decorator)
class CountCalls:
def __init__(self, func):
self.func = func
self.calls = 0
def __call__(self, *args, **kwargs):
self.calls += 1
print(f"函数 {self.func.__name__} 被调用第 {self.calls} 次")
return self.func(*args, **kwargs)
@CountCalls
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # 第一次调用
greet("Bob") # 第二次调用
输出:
函数 greet 被调用第 1 次
Hello, Alice!
函数 greet 被调用第 2 次
Hello, Bob!
(2)替代闭包(Closure)
class Adder:
def __init__(self, x):
self.x = x
def __call__(self, y):
return self.x + y
add5 = Adder(5)
print(add5(3)) # 输出 8
(3)模拟函数对象
class Power:
def __init__(self, exponent):
self.exponent = exponent
def __call__(self, base):
return base ** self.exponent
square = Power(2)
cube = Power(3)
print(square(4)) # 16 (4^2)
print(cube(3)) # 27 (3^3)
4. __call__
与普通方法的区别
特性 | __call__ 方法 | 普通方法(如 obj.method() ) |
---|---|---|
调用方式 | obj() | obj.method() |
用途 | 让对象像函数一样工作 | 普通类方法 |
适用场景 | 装饰器、函数式编程 | 常规 OOP 逻辑 |
5. 总结
✅ __call__
允许类的实例像函数一样被调用。
✅ 调用 obj(*args, **kwargs)
时,Python 会自动执行 obj.__call__(*args, **kwargs)
。
✅ 常见用途:装饰器、闭包替代、状态保持的函数。
通过 __call__
,你可以让对象更加灵活,适用于函数式编程场景! 🚀