类变量和实例变量在内存中是如何存储的?

发布时间:2026/6/29 17:37:54
类变量和实例变量在内存中是如何存储的? 一、先搞懂两个核心存储容器__dict__Python 中类、每个实例对象各自拥有独立的属性字典__dict__所有自定义属性都存在这里。类变量存放在 类对象的__dict__实例变量存放在 实例对象的__dict__1. 类对象的内存存储当你定义class A:时Python 在堆内存中创建一个type类型的类对象类中直接定义的变量、类方法、静态方法、装饰器属性全部存入A.__dict__所有实例不会复制这份字典只是通过属性查找链引用。示例python运行class A: cls_num 100 def func(self): pass print(A.__dict__) # 包含 cls_num、func 等类属性内存结构简图plaintext堆内存 ┌──────────── 类对象 A(type实例) ───────────┐ │ A.__dict__: {cls_num: 100, func: 函数地址...} │ └─────────────────────────────────────────────┘二、实例对象的内存存储执行a A()实例化在堆上创建实例对象分配对象头部信息引用计数、类型指针等默认创建空的实例属性字典a.__dict__实例初始不会拷贝任何类变量到自己的__dict__通过内部指针__class__指向所属类A找不到属性时向上去类的__dict__查找。python运行a A() print(a.__dict__) # 初始为空 {} print(a.__class__ is A) # True内存结构简图plaintext┌──── 实例对象 a ────┐ ┌──── 类对象 A ────┐ │ __class__ → 指向A │ │ A.__dict__ │ │ a.__dict__ {} │◄───────│ cls_num100 │ └───────────────────┘ └─────────────────┘三、两种变量详细存储规则1. 类变量存储规则仅存储一份无论创建多少个实例类变量只存在类的__dict__中访问规则A.cls_num直接查A.__dict__a.cls_num先查a.__dict__没找到再去A.__dict__查找通过类名赋值只会修改类__dict__里的值所有实例可见。2. 实例变量存储规则在__init__中用self.xxx 值属性写入当前实例自己的__dict__每一个实例都有独立的__dict__互不干扰只能通过当前实例访问类无法直接访问实例变量。python运行class A: cls_var 10 def __init__(self): self.ins_var 20 # 存入实例.__dict__ a1 A() a2 A() print(a1.__dict__) # {ins_var:20} print(a2.__dict__) # {ins_var:20} 两个独立字典内存结构plaintext实例a1__dict__ {ins_var:20} 实例a2__dict__ {ins_var:20} 类A__dict__ {cls_var:10}四、高频易错场景实例赋值同名类变量python运行class A: num 10 a A() a.num 99存储变化不会修改类的num在当前实例a.__dict__中新增键num 99后续a.num优先读取实例自己的属性屏蔽了类变量。内存结构plaintextA.__dict__: {num:10} a.__dict__: {num:99}五、可变类变量list/dict的存储特点python运行class A: lst [1,2] a A() a.lst.append(3)lst依然只存在类的__dict__所有实例引用同一个列表内存地址只是修改堆上列表内部数据没有在实例新建属性所以全部实例共享变化。六、slots对实例存储的改变优化存储默认实例靠__dict__存储属性开销大 使用__slots__后实例不再创建__dict__属性固定存在实例结构体的数组中内存大幅压缩不能动态新增实例属性只能使用 slots 定义的字段。python运行class A: __slots__ [name] cls_var 10 def __init__(self): self.name test # 实例没有 __dict__属性存在固定内存数组里七、整体存储总结表表格维度类变量实例变量存储位置类对象的__dict__每个实例各自的__dict__或__slots__数组内存份数全局仅 1 份N 个实例就 N 份独立存储创建时机类定义阶段实例化运行时一般__init__属性查找顺序实例→类直接当前实例生命周期类加载到程序结束实例创建到被 GC 回收需要我画一张完整的内存寻址流程图属性查找 MRO 链路吗