Python的__call__ 方法

在 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__,你可以让对象更加灵活,适用于函数式编程场景! 🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值