一段奇怪的Python代码,ChatGPT的解释——Python默认参数的可变对象共享
def foo(a, b=[]): b.append(a) return b print(foo(1)) print(foo(1)) print(foo(1))
这段代码会产生许多人可能意料之外的结果。以下是代码的行为以及背后的原因:
代码行为
def foo(a, b=[]): # 默认参数 b 是一个空列表
b.append(a) # 将 a 添加到 b
return b
print(foo(1)) # 第一次调用
print(foo(1)) # 第二次调用
print(foo(1)) # 第三次调用
输出
[1]
[1, 1]
[1, 1, 1]
原因
-
默认参数的可变对象共享
- 在 Python 中,默认参数只在函数定义时被评估一次。如果默认参数是一个可变对象(如列表或字典),它会在所有后续的函数调用中被共享。
- 因此,每次调用
foo
时,如果未显式传递参数b
,它会继续使用同一个b
(即最初创建的那个空列表)。
-
b 是同一个对象
- 每次调用
foo(1)
时,b.append(a)
会将值添加到同一个共享列表中,而不是重新创建一个新的列表。
- 每次调用
如何修复
如果希望每次调用 foo
时都使用一个新的空列表,可以将默认参数设置为 None
,并在函数内部进行处理:
def foo(a, b=None):
if b is None: # 检查 b 是否为 None
b = [] # 创建一个新的列表
b.append(a)
return b
print(foo(1)) # 输出: [1]
print(foo(1)) # 输出: [1]
print(foo(1)) # 输出: [1]
修复后的输出
[1]
[1]
[1]
总结
- 默认参数的可变对象(如列表或字典)会被所有调用共享,导致意外的累积效果。
- 解决方法是使用不可变的默认值(如
None
),并在函数内部显式创建新的对象。
Feel free to contact me on professional issue.
liveinspring@hotmail.com