文章目录
- @[TOC](文章目录)
- 前言
- 虽然 Python 底层依赖 C 语言的栈和堆,但 Python 对开发者屏蔽了这些细节。不过理解这个概念,对理解 Python 的内存管理和变量赋值非常有帮助。
- 一、核心图解
- 二、📖 详细解释
- 1.栈区(Stack)
- 2.堆区(Heap)
- 3.🔍 关键理解:变量是贴在对象上的标签
- 4.实战验证
- 5.📌 可变与不可变对象的区别
- 6.总结对比表
- 记忆口诀
文章目录
- @[TOC](文章目录)
- 前言
- 虽然 Python 底层依赖 C 语言的栈和堆,但 Python 对开发者屏蔽了这些细节。不过理解这个概念,对理解 Python 的内存管理和变量赋值非常有帮助。
- 一、核心图解
- 二、📖 详细解释
- 1.栈区(Stack)
- 2.堆区(Heap)
- 3.🔍 关键理解:变量是贴在对象上的标签
- 4.实战验证
- 5.📌 可变与不可变对象的区别
- 6.总结对比表
- 记忆口诀
前言
虽然 Python 底层依赖 C 语言的栈和堆,但 Python 对开发者屏蔽了这些细节。不过理解这个概念,对理解 Python 的内存管理和变量赋值非常有帮助。
一、核心图解
二、📖 详细解释
1.栈区(Stack)
存放内容:变量名和它们指向的引用地址(也就是堆区对象的地址)
特点:
存储的是引用(指针),不是实际数据
访问速度非常快(直接访问)
大小固定,由系统管理
遵循 LIFO(后进先出)原则
xm="小明"# 栈中存储变量名 xm,指向堆中的字符串"小明"age=18# 栈中存储变量名 age,指向堆中的整数 18dog1=Dog()# 栈中存储变量名 dog1,指向堆中的 Dog 实例对象2.堆区(Heap)
存放内容:所有实际的对象数据(字符串、数字、列表、实例等)
特点:
- 存储的是实际数据
- 访问速度相对较慢(需要间接寻址)
- 大小动态,由 Python 的垃圾回收机制管理
- 所有对象都在堆区创建
# 堆中存储的实际数据name="小明"# "小明" 这个字符串对象在堆中age=18# 18 这个整数对象在堆中numbers=[1,2]# [1, 2] 这个列表对象在堆中# 列表中存储的是对堆中 1 和 2 的引用3.🔍 关键理解:变量是贴在对象上的标签
在 Python 中,变量名实际上是一个贴在对象上的标签,而不是存储对象的盒子。
图解变量赋值
a=[1,2,3]# 创建列表对象,贴上标签 ab=a# 把标签 b 也贴到同一个对象上4.实战验证
classDog:def__init__(self,name):self.name=name dog1=Dog("旺财")dog2=dog1# dog2 和 dog1 指向同一个堆区对象print(id(dog1))# 0x7f8a1c2d3e4f(堆区地址)print(id(dog2))# 0x7f8a1c2d3e4f(完全相同!)# 验证它们指向同一个对象print(dog1isdog2)# True# 修改 dog1,dog2 也跟着变(因为指向同一个堆区对象)dog1.name="来福"print(dog2.name)# "来福"(确实变了!)5.📌 可变与不可变对象的区别
不可变对象(int, str, tuple)
修改时会创建新对象,重新绑定引用。
a=10# 栈中 a → 堆中地址 0xA0F0 (值10)a=20# 栈中 a → 堆中地址 0xA1F1 (值20,新创建)# 原来 0xA0F0 的 10 被垃圾回收了可变对象(list, dict, 自定义对象)
修改时不会创建新对象,直接修改堆中的数据。
lst=[1,2]# 栈中 lst → 堆中地址 0xB0F0lst.append(3)# 堆中地址 0xB0F0 的列表内容变为 [1, 2, 3]# 栈中 lst 仍然指向 0xB0F0(没变!)6.总结对比表
记忆口诀
栈存标签,堆存实物
变量是标签,不是盒子
修改可变对象,标签不动
修改不可变对象,标签换贴新实物
这个理解是 Python 内存管理的基石,掌握后对理解引用传递、深拷贝/浅拷贝、垃圾回收等问题会轻松很多!👍