You need to enable JavaScript to run this app. Python类与实例属性内存占用及类属性赋值行为机制咨询
优惠活动
大模型
产品
解决方案
定价
更多

Python类与实例属性内存占用及类属性赋值行为机制咨询

类属性的内存共享机制

针对你创建大量Sub实例的场景,直接给出结论:类属性attr存储的字典数据不会被复制成多份,所有未主动修改过该属性的Sub实例,对attr的引用全部指向同一个全局字典对象。

  • 类属性是挂载在类对象(Test类本身、以及继承它的Sub类对象)的属性字典上的,不属于任何单个实例的内存空间。
  • 通过实例访问属性时,Python会按照“先查实例自身属性字典、找不到再沿继承链向上查对应类的属性字典”的规则做查找。没有在自身字典中定义过attr的实例,访问该属性时本质都是读取类对象上挂载的唯一原始字典,全程不会发生数据拷贝。
  • 你可以快速验证这一点:对所有创建出的Sub实例执行id(实例.attr),只要实例没有被主动赋值过attr,这个返回的内存地址值完全一致,直接能证明它们指向同一个对象。
实例属性赋值与类属性的遮蔽逻辑

你观察到的“给单个实例赋值attr不会影响其他实例引用”的行为,是Python属性读写规则的直接结果,和你的预期偏差来自两个核心逻辑差异:

  • 读操作的查找规则:如前所述,访问属性时会从实例自身到类逐级向上查找,优先命中实例自己定义的同名属性,找不到才会读类上的属性。
  • 写操作的赋值规则:执行实例.属性名 = 值的赋值操作时,Python完全不会触发向上查找流程,默认会直接把这个键值对写入当前实例自己的属性字典,根本不会修改类对象上的同名属性。

对应你的测试代码逐段解释行为:

  1. 初始状态下,test1和test2的自身属性字典中都没有attr键,因此两者读取attr时都会找到类上挂载的共享原始字典,test1.attr == test2.attr返回True。
  2. 当执行test1.attr = {}时,Python没有去修改类上的原始attr,而是直接在test1的自身属性字典中新增了键为attr、值为新建空字典的条目。
  3. 后续读取test1.attr时,Python首先在test1自身的属性字典里找到了这个空字典,就不会再向上查找类上的共享对象;而test2的自身字典里依然没有attr键,它读取时还是会指向类上的原始共享字典,因此两者比较结果为False。

常见误区补充:
如果不重新给实例.attr整体赋值,而是直接修改这个共享字典的内容(比如写test1.attr["key"] = "value"),因为没有触发实例级的属性赋值流程,所有未单独定义过attr的实例都会同步看到这个改动,因为本质上它们都指向同一个被修改的原始字典。只有对实例.attr整体重新赋值时,才会在实例上创建一个遮蔽属性,切断对类属性的直接访问,完全不影响其他实例和类本身的原始属性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 04:54:04