以下问题,任何人都有足够长时间修补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中的静态变量,而没有繁殖错误?)

Edit

Baczek做了一个有趣的例子。以及您的大多数评论尤其是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从某种意义上说,线将是"混合"的,因为在定义上将发生(函数对象的绑定)的一部分,而在函数调用时间时(默认参数分配)的一部分(分配)。

实际行为更加一致:执行该线时,该行的所有内容都将在函数定义上进行评估。

答案

实际上,这不是设计缺陷,也不是因为内部或性能的原因。
它仅仅是从Python中的功能是一流的对象,而不仅仅是代码。

一旦您以这种方式想到它,就完全有道理:一个函数是对其定义进行评估的对象;默认参数是一种"成员数据",因此它们的状态可能会从一个呼叫变为另一个呼叫 - 与其他任何对象一样。

无论如何,Effbot对这种行为的原因有很好的解释python中的默认参数值
我发现它非常清楚,我真的建议阅读它,以更好地了解功能对象的工作方式。

来自: stackoverflow.com