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

为何cls.__getattribute__返回函数而非绑定方法,而cls.__call__返回绑定方法?

Python中cls.__getattribute__与cls.__call__的行为差异解析

先看示例代码及运行结果:

class cls:
    pass

# 交互环境输出
cls.__getattribute__          # <slot wrapper '__getattribute__' of 'object' objects>
object.__getattribute__       # <slot wrapper '__getattribute__' of 'object' objects>
cls.__getattribute__ is object.__getattribute__  # True
cls.__call__                  # <method-wrapper '__call__' of type object at 0x7fdee07ad110>
type.__call__.__get__(cls)    # <method-wrapper '__call__' of type object at 0x7fdee07ad110>

行为差异的核心原因

1. 类的双重身份是根源

Python里所有自定义类都有双重身份:

  • 它是**type的实例**(元类实例,类本身也是一个对象)
  • 它是**object的子类**(作为普通类,用于创建实例)

这两个身份对应两条完全独立的属性查找路径。

2. cls.__getattribute__的本质

__getattribute__是object类定义的实例方法,专门用来处理object实例(即cls()创建的对象)的属性查找逻辑。

当你访问cls.__getattribute__时,是从object继承来的类属性——但这个方法是给cls的实例用的,而cls本身是type的实例,并非object的实例,所以返回的是未绑定的槽函数,不会绑定到cls上。

3. cls.__call__的本质

__call__是type类定义的方法,作用是让类可以像函数一样被调用(比如cls()就是调用这个方法生成实例)。

cls是type的实例,根据描述符协议,type.__call__作为方法会自动绑定到cls这个实例上,所以返回的是绑定完成的方法包装器,和type.__call__.__get__(cls)的结果完全一致。

4. 为什么cls.__getattribute__不会去type中查找?

__getattribute__属于普通对象的属性查找逻辑:访问cls.__getattribute__时,Python会先在cls自身的字典中查找,找不到就沿着父类链(cls→object)查找,找到后直接返回。

而type中的__getattribute__是元类层面的方法,只有当你对cls这个元类实例执行属性查找时(比如type(cls).__getattribute__(cls, '__getattribute__'))才会触发这条路径,普通的cls.__getattribute__不会走元类的查找链。


内容的提问来源于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.27 02:10:22