为何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
相关产品推荐
相关产品推荐

