Python函数参数默认值作用域疑问:为何列表默认值持续更新?
Python可变默认参数的陷阱解析
问题重现
你的代码片段:
def fun(i = []): print("i is", i) i.append(1) for k in range(5): print("k is", k) fun()
实际运行输出:
k is 0 i is [] k is 1 i is [1] k is 2 i is [1, 1] k is 3 i is [1, 1, 1] k is 4 i is [1, 1, 1, 1]
预期输出:
k is 0 i is [] k is 1 i is [] k is 2 i is [] k is 3 i is [] k is 4 i is []
核心原因
Python函数的默认参数是在函数定义阶段初始化的,而不是每次调用函数时重新创建。
对于def fun(i=[]),这个空列表[]在解释器加载函数定义时就已经被创建,作为函数对象的固定属性保存下来。每次调用fun()且不传入参数时,变量i都会指向这个已存在的列表对象——而非每次生成新的空列表。
因为列表是可变对象,i.append(1)会直接修改这个共享的列表本身,所以后续调用能看到之前的修改结果。
这里的参数作用域没问题:i确实是函数调用时的局部变量,但这个局部变量指向的是函数定义时创建的外部可变对象,修改对象本身会影响后续调用。
解决方案
如果想要每次无参调用时都使用全新的空列表,正确写法是把默认参数设为None,在函数内部动态创建列表:
def fun(i=None): # 未传入参数时,创建新的空列表 if i is None: i = [] print("i is", i) i.append(1)
这样每次调用fun()时,都会在函数内部生成新的空列表,不会共享状态,就能得到你预期的输出。
内容的提问来源于stack exchange,提问作者Hari Krishnan
相关产品推荐
相关产品推荐

