长时间修改Python的任何人都被以下问题咬伤(或弄成碎片):
def foo(a=[]):
a.append(5)
return a
Python新手希望此函数始终返回仅包含一个元素的列表[5]
。结果是非常不同的,并且非常令人惊讶(对于新手而言):
>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
>>> foo()
[5, 5, 5, 5]
>>> foo()
我的一位经理曾经第一次遇到此功能,并将其称为该语言的“巨大设计缺陷”。我回答说,这种行为有一个潜在的解释,如果您不了解内部原理,那确实是非常令人困惑和意外的。但是,我无法(对自己)回答以下问题:在函数定义而不是函数执行时绑定默认参数的原因是什么?我怀疑经验丰富的行为是否具有实际用途(谁真正在C中使用了静态变量,却没有滋生bug?)
编辑:
巴泽克举了一个有趣的例子。连同您的大多数评论,特别是Utaal的评论,我进一步阐述了:
>>> def a():
... print("a executed")
... return []
...
>>>
>>> def b(x=a()):
... x.append(5)
... print(x)
...
a executed
>>> b()
[5]
>>> b()
[5, 5]
在我看来,设计决策似乎与将参数范围放置在何处有关:在函数内部还是“一起”使用?
在函数内部进行绑定将意味着x
在调用该函数(未定义)时,该绑定实际上已绑定到指定的默认值,这会带来深层的缺陷:def
从绑定的一部分(即函数对象)将在定义时发生,部分(默认参数的分配)将在函数调用时发生。
实际行为更加一致:执行该行时将评估该行的所有内容,即在函数定义时进行评估。
[5]
。我是Python的新手,我不会期望这样做,因为显然foo([1])
会返回[1, 5]
,而不是[5]
。您的意思是说,新手希望没有参数的函数将始终返回[5]
。