Python中堆存对象、栈存引用;堆由解释器管理并自动回收,栈由操作系统分配且随函数调用自动进出;所有Python对象均在堆上创建,栈仅存储变量名到堆对象的绑定关系。

Python 中的“堆”和“栈”不是语言层面显式暴露给开发者的内存管理概念,而是底层 CPython 解释器运行时依赖的两种内存区域,它们在对象生命周期、分配方式和管理责任上存在本质区别。
堆(Heap):动态分配,存放 Python 对象
CPython 中所有 Python 对象(如列表、字典、字符串、类实例等)都分配在堆内存中。堆由解释器统一管理,支持动态申请和释放,大小不固定,可增长。
- 对象创建即分配在堆上,例如 a = [1, 2, 3] 创建的列表对象存于堆
- 引用变量(如 a)本身不存对象,只存指向堆中对象的指针
- 垃圾回收(GC)主要作用于堆内存,通过引用计数 + 循环检测机制自动回收不可达对象
- 程序员无法手动释放堆内存,也不需关心具体地址或大小
栈(Stack):函数调用专用,存放局部变量和执行上下文
栈由操作系统为每个线程分配,用于维护函数调用过程中的临时数据。CPython 的栈帧(frame)也位于此,但注意:栈上只存“引用”,不存实际对象。
- 函数调用时压入栈帧,包含局部变量名、字节码指令位置、异常处理信息等
- 局部变量(如 x = 10 或 s = "hello")在栈帧中存储的是名字到堆对象的绑定关系
- 函数返回时栈帧自动弹出,局部变量名失效,若无其他引用,对应堆对象可能被 GC 回收
- 栈空间有限,深度递归易导致 RecursionError: maximum recursion depth exceeded
关键区别一目了然
对比核心维度:
立即学习“Python免费学习笔记(深入)”;
- 谁分配? 堆由 Python 内存分配器(pymalloc)管理;栈由操作系统在线程创建时分配
- 存什么? 堆存实际对象数据;栈存函数调用状态 + 变量名与对象的映射
- 生命周期? 堆对象存活取决于引用;栈帧存活仅限函数执行期间
- 会不会溢出? 堆不够会抛 MemoryError;栈过深抛 RecursionError 或段错误(极少见)
常见误解澄清
有些说法如“小整数/短字符串在栈上”或“list 在栈、元素在堆”是不准确的:
- 所有 Python 对象——无论多小——都在堆上创建,包括 int、str、tuple
- 栈上只有名字(标识符)和指向堆对象的指针,没有“值拷贝”(除非是 C 扩展中显式操作)
- 所谓“栈变量”只是 C 层面的局部指针变量(如 PyObject *p),对 Python 程序员完全透明











