任何修补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()
我的一位经理曾经第一次接触到这个特性,并称它为该语言的“一个戏剧性的设计缺陷”。我回答说,这种行为有一个潜在的解释,如果你不理解内部,这确实是非常令人费解和意想不到的。然而,我无法(对自己)回答以下问题:是什么原因在函数定义时绑定default参数,而不是在函数执行时?我怀疑经验丰富的行为是否有实际用途(谁真的在C中使用了静态变量,而没有滋生错误?)
编辑:
Baczek举了个有趣的例子。连同你的大多数评论和尤其是尤塔尔,我进一步阐述了:
>>> def a():... print("a executed")... return []...>>>>>> def b(x=a()):... x.append(5)... print(x)...a executed>>> b()[5]>>> b()[5, 5]
对我来说,设计决策似乎是相对于参数的范围:在函数内部,还是与它“一起”?
在函数内部进行绑定将意味着x
在函数被调用时有效地绑定到指定的默认值,而不是定义,这将呈现一个严重的缺陷:def
行将是“混合”,因为部分绑定(函数对象)将在定义时发生,部分(默认参数的分配)在函数调用时发生。
实际行为更加一致:该行的所有内容在执行该行时都会被评估,这意味着在函数定义时。