Python变量内存地址分配机制及赋值行为技术疑问
Python变量内存分配与列表append机制答疑
问题背景
用户基于三个测试案例,对Python的变量内存分配、列表append机制存在疑问,先明确三个测试的代码与结果:
测试1:循环生成不同值的变量
ls = [] for i in range(0,10): a = 1 + i print(id(a)) ls.append(a) ls
- 输出:每次
id(a)均不相同 - 最终列表:
[1,2,...,10]
测试2:循环赋值相同值的变量
ls = [] for i in range(0,10): a = 1 print(id(a)) ls.append(a) ls
- 输出:每次
id(a)始终一致 - 最终列表:由10个
1组成的列表
测试3:赋值后修改变量
ls = [] for i in range(0,10): a = 1 print(id(a)) ls.append(a) a = 10 print(id(a)) ls
- 输出:每次循环先输出
1的地址,后输出10的地址 - 最终列表:仍为10个
1
核心疑问解答
1. Python如何为变量分配内存地址?
Python中的变量本质是对内存中对象的引用,并非直接存储值。执行赋值语句时,Python会先检查内存中是否存在对应值的对象:
- 若存在,让变量直接指向该对象的地址;
- 若不存在,才会创建新的对象,再让变量指向新对象的地址。
针对小整数(通常范围是-5到256,具体依赖Python实现),Python会提前在内存中创建并缓存这些对象,也就是“小整数池”机制。测试2中每次a=1,变量a都会指向缓存好的同一个1对象,因此id(a)始终相同;测试1中a=1+i生成的是1到10的不同数值,每个数值对应不同的缓存对象,所以id(a)每次都不同。
2. 为什么修改变量a的值不会影响列表中的元素?
列表ls中存储的是对象的引用,而非变量a的引用。执行ls.append(a)时,是把a当前指向的对象地址存入列表。后续修改a=10,只是让变量a转而指向值为10的新对象,并不会改变列表中已存储的、指向1的引用。
简单来说:你把写着“1的地址”的纸条放进列表,之后自己手里的纸条换成“10的地址”,但列表里的纸条还是原来那一张,所以列表元素不会变化。
3. 为什么相同值复用地址、修改值则更换地址?
- 相同值复用地址:源于Python的对象缓存机制,比如小整数池、字符串驻留(部分字符串会被缓存)。这种机制能节省内存,避免重复创建相同值的对象,所以测试2中每次赋值
a=1都会复用同一地址。 - 修改值则更换地址:Python中的整数、字符串属于不可变对象,无法直接修改原对象的值。当你试图“修改”变量的值时,实际是创建一个新的对象,再让变量指向这个新对象的地址。比如测试3中
a=10,是新建了值为10的对象,a转而指向新地址,原1对象未被修改,列表中的引用也保持指向1的地址。
内容的提问来源于stack exchange,提问作者Johnny C.
相关产品推荐
相关产品推荐

