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

Python中X.__getitem__(1)与type(X).__getitem__(X,1)调用差异问题

Python属性查找差异原理分析

首先整理示例代码如下:

class C:
    data = 'spam'
    def __getattr__(self, name):
        print('getattr:', name)
        return getattr(self.data, name) 
X = C()
X.__getitem__(1) # <-- 正常运行
type(X).__getitem__(X, 1) # <-- 抛出AttributeError: type object 'C' has no attribute '__getitem__'

两种调用的本质差异

  • 调用X.__getitem__(1)时,属性查找的主体是实例X,走实例的普通属性查找流程
  • 调用type(X).__getitem__(X, 1)时,属性查找的主体是类C,走类的属性查找流程,和实例X的属性逻辑无关

第一种调用正常运行的原因

实例属性查找的完整顺序为:

  1. 检查实例自身的__dict__中是否存在__getitem__属性,不存在
  2. 检查实例所属类C及其父类的__dict__中是否存在__getitem__属性,不存在
  3. 触发实例绑定的__getattr__方法,返回data属性的__getitem__方法,调用后正常得到结果。

第二种调用抛出异常的原因

类属性查找的完整顺序为:

  1. 检查类C自身的__dict__中是否存在__getitem__属性,不存在
  2. 检查类C的父类(默认继承object)的__dict__中是否存在__getitem__属性,不存在
  3. 此时会触发类C自身的__getattr__方法,而你代码中只给实例定义了__getattr__,类C本身没有该方法,因此直接抛出AttributeError。

补充:普通类中定义的__getattr__仅作用于该类的实例对象,若要自定义类层面的缺失属性处理逻辑,需要给类的元类定义__getattr__方法。

关于显式调用特殊方法的疑问

你提到的隐式调用特殊方法(如X[1])跳过__getattr__是另一套规则:Python解释器处理运算符对应的隐式特殊方法调用时,会直接从类层面开始查找特殊方法,不会走实例的普通属性查找流程,因此也不会触发实例的__getattr__。而本次你遇到的两种显式调用的差异,本质是属性查找的主体不同,和特殊方法的隐式调用规则无关。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 08:45:02