Python 3.13中类实例__dict__内存占用差异原因咨询
以下代码在Python 3.13中运行:
import sys class Vector: def __init__(self, x, y): self.x = x self.y = y v1 = Vector(1, 2) v2 = Vector(1, 2) print(f"v1 __dict__ : {sys.getsizeof(v1.__dict__)} bytes") print(f"v2 __dict__ : {sys.getsizeof(v2.__dict__)} bytes") v3 = Vector(1, 2) v4 = Vector(1, 2) print(f"v3 __dict__ : {sys.getsizeof(v3.__dict__)} bytes") print(f"v4 __dict__ : {sys.getsizeof(v4.__dict__)} bytes") v5 = Vector(1, 2) print(f"v5 __dict__ : {sys.getsizeof(v5.__dict__)} bytes") v6 = Vector(1, 2) print(f"v6 __dict__ : {sys.getsizeof(v6.__dict__)} bytes")
输出结果:
v1 __dict__ : 288 bytes v2 __dict__ : 288 bytes v3 __dict__ : 272 bytes v4 __dict__ : 272 bytes v5 __dict__ : 264 bytes v6 __dict__ : 256 bytes
疑问点:
- 为何不同Vector实例的__dict__内存占用不同?
- 调整print语句位置会改变结果的原因是什么?
- v2与v3的内存占用为何存在差异?
- 该代码在不同Python版本中表现不同的原因?
解答
1. 不同实例__dict__内存占用不同的原因
Python的__dict__是存储实例属性的字典对象,Python 3.13对小字典的内存分配做了精细优化。当重复创建结构完全相同的实例时,解释器会识别出__dict__的键模式(这里固定是x和y两个键),后续实例的__dict__会复用已识别的结构信息,采用更紧凑的内存布局,避免默认字典的冗余预留空间,因此内存占用逐步降低。
2. 调整print语句位置会改变结果的原因
核心在于实例创建顺序与解释器的优化时机。如果先批量创建所有实例再统一打印,解释器会在创建过程中完成对实例__dict__结构的识别,所有实例的__dict__会直接使用优化后的内存布局,内存占用会趋于一致。而原代码中穿插的print语句,相当于打断了连续的实例创建流程,前两个实例创建后立即打印时,解释器还未完成结构优化,后续实例则在优化生效后创建,因此出现差异。
3. v2与v3内存占用存在差异的原因
v2属于前两个创建的实例,此时解释器还处于“学习”该类实例__dict__结构的阶段,它的__dict__使用的是字典默认的内存分配逻辑(预留了额外空间);而v3是在v1、v2创建并打印之后生成的,此时解释器已经确定该类实例的__dict__只会包含固定的两个键,因此为v3分配了更紧凑的内存空间,不再保留冗余预留,所以内存占用更低。
4. 不同Python版本表现不同的原因
Python的字典实现一直在迭代优化:
- 3.7之前字典无序,3.7+改为有序;
- 3.10引入紧凑字典优化,压缩小字典的内存占用;
- 3.13进一步针对同结构实例的
__dict__做了动态优化,根据创建顺序调整内存分配策略。
不同版本的内存管理逻辑、字典优化程度不同,导致相同代码的输出结果不一致。比如在Python 3.10及更早版本中,可能所有实例的__dict__内存占用都相同,因为当时的优化还未覆盖动态调整的场景。
内容的提问来源于stack exchange,提问作者Johnson Francesca

