`__call__` 方法的使用场景

This article is extracted from the chat log with AI. Please identify it with caution.

__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))  # 输出: 15

2. 实现装饰器类#

类装饰器通常使用 __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())  # 输出: 2

5. 实现策略模式#

根据不同情况选择不同的算法或行为。

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

注意事项#

  1. __call__ 方法可以接受任意参数,就像普通函数一样
  2. 使用 callable(obj) 可以检查对象是否可调用
  3. 不要过度使用 __call__,只有在确实需要函数行为时才使用
  4. 使用 __call__ 可能会降低代码的可读性,因为对象看起来像函数但实际上是类实例

__call__ 方法提供了一种强大的方式,让对象可以拥有函数的行为,同时保持对象的特性(如状态保存、继承等)。

本文共 633 字,创建于 Sep 1, 2025

相关标签: Python, ByAI