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

Python类__getitem__、__setitem__的用途及与get/set装饰器的差异

Python __getitem__与__setitem__方法相关问题解答

1. getitem、__setitem__的额外用途及与property装饰器的差异

自定义类中除语法访问外的其他用途

  • 实现类的迭代能力:只要自定义类实现了__getitem__,实例就可以直接被for循环遍历,也支持iter()、next()等迭代操作,甚至不需要额外实现__iter__方法;同时in关键字判断成员存在性时也会默认调用__getitem__遍历匹配。
  • 对齐标准容器的使用体验:自定义映射/序列类型时,通过这两个方法可以让类实例获得和原生字典、列表完全一致的方括号操作逻辑,降低使用者的学习成本,常见于自定义ORM模型、配置管理类等场景。
  • 兼容通用工具逻辑:大量Python内置及第三方工具函数默认对支持方括号访问的对象做读写操作,自定义类实现这两个方法后可以直接接入这类工具,无需修改工具源码。

与get/set装饰器(property)的差异

  • 作用对象不同:
    • __getitem__/__setitem__面向运行时传入的动态键/索引,支持处理任意数量、任意命名的键值,不需要提前声明。
    • property装饰器(即你说的get、set装饰器)面向预定义的固定属性,每个属性都需要单独编写对应的get/set方法,只能处理提前明确的属性名。
  • 调用逻辑不同:
    • 仅当使用方括号语法obj[key]访问时才会触发这两个dunder方法,读写逻辑完全由自定义实现决定,和实例自身的属性没有强制关联。
    • 仅当使用点语法obj.attr访问预定义的property属性时才会触发装饰器对应的方法,未预定义的属性会走默认的属性查找逻辑,和property无关。

2. 类与实例的同名属性访问规则

点语法访问属性时遵循「从下到上」的就近查找规则,优先级如下:

  1. 优先查找实例自身的__dict__属性,实例自身绑定的属性优先级最高,测试代码中d.newkey返回?就是因为实例自身有newkey属性,覆盖了类属性。
  2. 实例自身没有对应属性时,会查找实例所属类的__dict__,也就是类属性,测试代码中ADict.newkey返回!就是直接访问类层级的属性。
  3. 类层级也没有对应属性时,会按照类的方法解析顺序(MRO)向父类逐层查找。
  4. 所有层级都找不到对应属性时,抛出AttributeError。

注意:上述规则仅适用于点语法obj.attr访问,方括号obj[key]的访问逻辑完全由自定义的__getitem__实现决定,和这套属性查找规则无关。


测试代码最后一行报错原因

print(d.oldkey)走的是点语法属性查找逻辑:

  1. 实例d的__dict__中只有data、newkey两个属性,不存在oldkey。
  2. 类ADict的__dict__中也没有oldkey属性,父类也没有对应定义,因此抛出AttributeError。
    你之前执行的d['oldkey'] = 'notnew'触发的是自定义的__setitem__方法,只是将键值对存入了实例内部的self.data字典中,没有将oldkey绑定为实例的属性,因此只能通过d['oldkey']访问到对应值,无法通过点语法访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:09:04