为什么Python中list可在函数内原地修改生效,int却不行?
问题核心原理:可变对象与不可变对象的差异
你看到的表现差异和Python的作用域规则没有关系,核心是Python的「对象类型特性」+「参数传递规则」共同导致的:
1. Python统一的参数传递规则:传对象引用
Python所有函数参数传递的都是对象的引用副本,既不是值拷贝,也不是直接传原变量本身:
- 函数拿到的参数,和外层变量指向同一个内存地址的对象
- 但函数内部的参数名本身是独立的局部变量,和外层变量是两个独立的引用
2. list修改生效的原因(可变对象特性)
list属于可变对象,内存中存储的内容可以被直接修改:
你调用list_obj.append(n)时,没有修改list_obj这个引用的指向,只是在引用指向的原list对象的内存地址上新增了元素,所以外层指向同一个list对象的变量,自然能看到修改后的内容。
补充验证:如果你在函数内给list参数重新赋值(比如
list_obj = [1,2,3]),外层的list同样不会变化,因为你修改了函数内引用的指向,和原引用无关。
3. int修改不生效的原因(不可变对象特性)
int属于不可变对象,同类的还有str、tuple、float等,这类对象一旦创建,内存中的值就不能被修改:
你写int_obj += 1时,本质不是修改原int对象的值,而是会创建一个值为原int值+1的全新int对象,再把函数内部的局部引用int_obj指向这个新对象。外层的原引用还是指向原来的int对象,所以不会有任何变化。
你提到的返回新值再赋值的方案能生效,本质就是把函数内创建的新int对象的引用,重新赋值给外层的变量,自然就能更新值了。
简单验证
你可以用Python内置的id()函数(查看对象的内存地址)直观验证这个差异:
# 不可变对象int的地址变化 int_val = 0 print(id(int_val)) # 输出初始内存地址 int_val += 1 print(id(int_val)) # 地址发生变化,已经是新的对象 # 可变对象list的地址变化 list_val = [] print(id(list_val)) # 输出初始内存地址 list_val.append(1) print(id(list_val)) # 地址不变,还是原来的对象
内容的提问来源于stack exchange,提问作者TRN
相关产品推荐
相关产品推荐

