__call__ 是 Python 中的一个特殊方法(魔术方法),它允许类的实例像函数一样被调用。当一个类定义了 __call__ 方法后,该类的实例就可以使用函数调用语法 instance()。
主要使用场景#
1. 创建可调用对象#
让对象表现得像函数一样,可以保存状态并在多次调用间保持状态。
class Adder:
def __init__(self, base=0):
self.base = base
def __call__(self, x):
return self.base + x
add_five = Adder(5)
print(add_five(3)) # 输出: 8
print(add_five(10)) # 输出: 152. 实现装饰器类#
类装饰器通常使用 __call__ 方法来实现。
class Timer:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
import time
start = time.time()
result = self.func(*args, **kwargs)
end = time.time()
print(f"{self.func.__name__} 执行时间: {end - start:.4f}秒")
return result
@Timer
def expensive_operation(n):
return sum(i * i for i in range(n))
result = expensive_operation(10000)3. 实现函数记忆化(Memoization)#
保存函数调用的结果,避免重复计算。
class Memoize:
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
if args not in self.cache:
self.cache[args] = self.func(*args)
return self.cache[args]
@Memoize
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10)) # 快速计算,因为有记忆化4. 创建具有状态的函数#
传统函数不能保持状态(除非使用全局变量),但使用 __call__ 可以创建有状态的函数。
class Counter:
def __init__(self):
self.count = 0
def __call__(self):
self.count += 1
return self.count
counter = Counter()
print(counter()) # 输出: 1
print(counter()) # 输出: 25. 实现策略模式#
根据不同情况选择不同的算法或行为。
class Strategy:
def __call__(self, a, b):
raise NotImplementedError
class AddStrategy(Strategy):
def __call__(self, a, b):
return a + b
class MultiplyStrategy(Strategy):
def __call__(self, a, b):
return a * b
# 使用策略
calculator = AddStrategy()
result = calculator(5, 3) # 输出: 8
calculator = MultiplyStrategy()
result = calculator(5, 3) # 输出: 15注意事项#
__call__方法可以接受任意参数,就像普通函数一样- 使用
callable(obj)可以检查对象是否可调用 - 不要过度使用
__call__,只有在确实需要函数行为时才使用 - 使用
__call__可能会降低代码的可读性,因为对象看起来像函数但实际上是类实例
__call__ 方法提供了一种强大的方式,让对象可以拥有函数的行为,同时保持对象的特性(如状态保存、继承等)。