无法理解为什么当您重复调用同一函数时python不重用该参数

时间:2018-07-22 14:01:43

标签: python

我正在观看有关python的教程,它使用了以下示例:

def add_spam(menu=[]):
    menu.append("spam")
    return menu

如果反复调用add_spam(),则菜单列表的大小会增加。这对我来说是新的,因为我来自C#背景。但是,还可以。

要解决此问题,它说您应该将菜单参数设置为None,但我不明白为什么这样。这是他们使用的代码:

def add_spam(menu=None):
    if menu is None:
        menu = []
    menu.append('spam')
    return menu

如果您第一次调用它,尽管菜单将被设置为[],并且第二次确定它是否像在第一个示例中那样“记住”参数,那么菜单在那时将是[],因此它将只是如第一个示例一样,将垃圾邮件添加到列表中。

除了您应该使用不可变类型之外,视频忽略了任何解释,所以我无法理解其工作原理。

编辑cos我还是不明白:

我看到的是该函数捕获了变量,因此它使用menu = []并将其秘密存储在某个地方,想象一个名为_menu的私有变量,这样,如果再次调用它,它就不会重新求值它只是继续使用_menu,因此会不断增长。

在第二个示例中,我不明白为什么它不只是简单地使用menu = None并将 秘密存储为_menu,所以_menu = None,然后当您调用第二个函数时,它设置_menu = []并与第一个示例完全一样并不断增长。

“无”是不可变的这一事实与我似乎无关,因为您没有做“ None = []”,而是在做“ menu =” [],因此菜单不再是以前的样子,变成了[],而可以根据需要进行修改。

除非这是一些硬编码功能,否则如果您将它设置为None,则不会执行复制行为,那么我将不了解两者之间的区别。

2 个答案:

答案 0 :(得分:4)

  

Python的默认参数在定义函数时只计算一次,而不是在每次调用函数时都被求值(例如Ruby)。

https://docs.python-guide.org/writing/gotchas/

从Python的文档中获取更多详细信息:

  

执行功能定义时,从左到右评估默认参数值。这意味着在定义函数时,表达式将被计算一次,并且每次调用都使用相同的“预先计算”值。

https://docs.python.org/3/reference/compound_stmts.html#function-definitions

列表是可变对象,而None是不可变的,因此您会看到这种行为。

答案 1 :(得分:3)

在函数内设置menu = []只是将名称menu重新绑定到该函数调用范围内的新对象。它不会在定义函数的范围内更改原始menu对象。另一方面,附加到函数内的menu实际上会修改与函数定义中的名称menu关联的内存中的对象(因为列表是可变的)。该对象是在首次定义函数时创建的,并且在函数调用之间共享。

如果您想了解更多信息,请查看python作用域/命名空间行为,其中默认参数共享主要只是其中的一部分。但基本上,

def foo(bar=None): #executed once
    bar = [] #executed every time the function is called