我已经将这个简单的代码简化为更大的 python 代码中的意外行为:
def f(n, s=[]):
s.append(n)
return s
print(f(3))
print(f(5))
给出的输出是:
[3]
[3, 5]
我期望:
[3]
[5]
如果明确给出空列表作为参数,则 f(5, s=[ ]),它按预期工作。我认为这是一个不好的做法,有人发生过这种情况吗?
(该函数看起来没用,但原始函数内部采样了一些随机变量)
这是 Python 中一个常见且令人困惑的方面,它与可变默认参数有关。观察到的行为的原因是默认参数(在本例中为
s=[]
)在函数定义时
只评估一次
,而不是在每次调用时评估。
让我们逐步分解一下:
-
函数定义: 当定义
def f(n, s=[]):
时,将创建一个列表[]
并将其分配给参数s
。这个列表成为f
函数的默认值。 -
第一次调用: 当调用
f(3)
时,由于没有提供s
的值,因此它使用默认值(之前创建的列表)。3
被追加到此列表中,并且函数返回[3]
。 -
第二次调用: 当调用
f(5)
时, 仍然使用相同的默认列表 (现在包含[3]
)。5
被追加到此列表中,因此函数返回[3, 5]
。
为什么这被认为是“陷阱”?
因为默认参数只评估一次,所以如果修改了一个可变默认参数(例如列表或字典),则该修改将保留在后续函数调用中。这通常不是预期的行为,并且可能导致难以调试错误。
如何避免这个问题:
推荐的解决此问题的方法是使用
None
作为默认值,并在函数体内检查参数是否为
None
。如果是
None
,则创建一个新的空列表:
def f(n, s=None):
if s is None:
s = []
s.append(n)
return s
print(f(3)) # 输出:[3]
print(f(5)) # 输出:[5]
在这种情况下,每次调用
f
而不提供
s
的值时,都会创建一个新的空列表。
希望这可以解释观察到的行为!
标签:python,function From: 78780646