You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何用@property装饰__call__后,Python实例调用与类直接调用行为矛盾?

问题:为何a()能正常调用但type(a).__call__(a)报错?

先看这段代码:

class A:
    @property
    def __call__(self):
        def inner():
            return 'Called.'
        return inner

a = A()
a() # 返回 'Called.'

type(a).__call__(a) # 报错:'property' object is not callable. 

根据Python官方文档描述:

object.__call__(self[, args...]) Called when the instance is “called”
as a function; if this method is defined, x(arg1, arg2, ...) roughly
translates to type(x).__call__(x, arg1, ...).

实际运行结果和文档描述看似矛盾,背后的核心原因是双下划线方法的查找逻辑和普通属性/方法存在差异,具体拆解为两点:

  • 执行a()时,Python会优先从实例a的属性集合中查找__call__。由于你给__call__加了@property装饰器,访问a.__call__会触发property的getter方法,返回内部定义的inner可调用函数,所以a()本质等价于(a.__call__)(),自然能正常执行并返回结果。

  • 调用type(a).__call__(a)时,你直接访问的是类A中定义的__call__属性——也就是那个property对象本身,而非经过实例触发getter后得到的可调用函数。这个property对象本身不具备可调用性,因此会抛出“'property' object is not callable”的错误。

官方文档里的等价描述,是针对常规类级别的__call__方法定义(即未用@property装饰的情况)。当你用@property把__call__改造成实例属性的动态getter时,就绕过了类级方法的常规调用逻辑,从而出现了看似矛盾的现象。

内容的提问来源于stack exchange,提问作者Zhang Daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 12:15:14