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

使用__slots__时类变量赋值覆盖所有实例同名属性的原因是什么?

该现象的底层原理
  • 使用__slots__声明属性时,Python会在类层面为每个声明的属性创建一个描述器对象,负责读写实例内存中预留的固定槽位数据。开启__slots__的类实例默认不会生成__dict__属性字典,所有声明属性的读写都由对应的类层面描述器完成。
  • 正常读取实例的name属性时,描述器的__get__方法会优先返回当前实例槽位中存储的值;如果实例槽位未赋值,才会降级到类层面的同名属性取值。
  • 当你执行Person.name = 'hacked'操作时,本质是把类层面原本的name描述器直接替换成了普通字符串类变量,原来负责读取实例槽位的逻辑被彻底覆盖。
  • 此时再访问p1.name/p2.name时,由于实例没有__dict__存储自有属性,会直接读取类层面的name字符串值,所以所有实例返回的都是同一个hacked结果。

补充验证:之前写入实例槽位的mc、pp值并没有丢失,只要把类层面的name描述器恢复,就能重新读到原来的实例值,示例如下:

# 提前保存原始描述器
orig_name = Person.name
Person.name = 'hacked'
print(p1, p2) # 输出 hacked hacked
# 恢复描述器
Person.name = orig_name
print(p1, p2) # 输出 mc pp
解释器未阻止该操作的原因
  • Python的设计遵循"成年人共识"原则,默认信任开发者知道自己在做什么,不会做过多的语法层强制限制。
  • 类层面给__slots__同名属性赋值本身是合法的使用场景:可以通过类层面赋值为槽位属性设置全局默认值,所有未单独赋值的实例都会继承该默认值,这是官方允许的合理用法。
  • __slots__的设计目标只是优化内存占用、加快属性访问速度,并没有限制类属性修改的额外规则,所以解释器不会拦截对类层面槽位对应属性的赋值操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 19:24:01