Python中为何内部函数可修改列表变量却无法修改整数变量?
为什么嵌套函数里修改int和list的结果不一样?
这问题问到点子上了!本质是Python的变量作用域规则和可变/不可变类型的特性在共同起作用,咱们掰开了说:
先看第一个int的例子
你这段代码里:
def K(): nums = 4 def helper(x): nums = helper(3) # 这里是关键! return nums print(K()) # 输出4
当helper函数里写nums = ...的时候,Python会默认把这个nums当成helper函数的局部变量——只要你在函数内部对变量做赋值操作,Python就会认为你要定义一个新的局部变量,除非你用nonlocal或者global明确声明要使用外层的变量。
所以这里的nums和外层K函数里的nums完全是两个独立的变量,外层的nums自始至终都是4,自然返回4。
再看第二个list的例子
换成列表之后:
def K(): nums = [0] def helper(x): nums[0] = x # 这里不是赋值变量本身! helper(3) return nums print(K()) # 输出[3]
这里的操作nums[0] = x不是给nums变量重新赋值,而是原地修改nums指向的那个列表对象的内部元素。这时候Python会按照LEGB作用域规则(局部→嵌套→全局→内置)去找nums的定义,找到了外层K函数里的列表,然后直接修改这个列表的内容。因为列表是可变类型,可以在原地修改内部数据,不需要重新给nums变量赋值,所以不会触发局部变量的定义,外层的列表自然被改了。
核心区别总结
- 不可变类型(int、str、tuple等):它们的值一旦创建就没法原地修改,所有看似“修改”的操作都是创建新对象并赋值给变量,这就会触发局部变量的定义,和外层变量彻底无关。
- 可变类型(list、dict、set等):可以直接修改内部元素,不需要改变变量本身的指向,所以会直接操作外层作用域里的那个对象。
额外小测试:怎么让int的例子也能修改?
只要用nonlocal声明要使用外层嵌套作用域的变量就行:
def K(): nums = 4 def helper(x): nonlocal nums # 明确告诉Python用外层的nums nums = x helper(3) return nums print(K()) # 输出3
内容的提问来源于stack exchange,提问作者Loki Stark
相关产品推荐
相关产品推荐

