跨越调用在Python中更新默认参数

时间:2013-05-09 01:21:35

标签: python python-2.7 python-3.x

在以下函数中,L会在每次调用时存储值。

例如,如果我拨打f(1),则L现在为[1]。当我再次调用它时,前一个L附加了新值。所以现在L是[1,1]

def f(a, L=[]):

    L.append(a)
    return L

但是在这个功能中:

i = 5

def f(arg=i):

    print arg
i = 6

无论我多少次调用此函数,参数仍为5 - 它在调用之间不会保持更新。

为什么不进行更新但列表有什么原因?

2 个答案:

答案 0 :(得分:3)

这是一个很好的问题。发生这种情况的原因是因为函数的默认参数作为单个对象存储在内存中,而不是每次调用函数时都重新创建。

因此,当您将列表[]作为默认参数时,在该程序的持续时间内只会有一个列表永远存在。因此,当您添加到列表时,您将添加到列表的那一个副本。对于像5这样的数字,情况仍然如此。但是,数字在Python中是不可变的,因此当您更改以数字开头的默认参数时,您实际上是指向一个新数字而不是编辑该5对象,而列表上的许多操作都会变异列表就位而不是返回新列表。

http://docs.python.org/3/tutorial/controlflow.html#default-argument-values

  

重要警告:默认值仅评估一次。这个   当默认值是可变对象(如a)时,会有所不同   列表,字典或大多数类的实例。

推荐的解决方案,如果你需要一个空列表默认​​参数的行为,而不是每次调用该函数都有相同的空列表默认​​参数,那就是这样做:

def f(a, L = None):

    if L is None:
        L = []
    L.append(a)
    return L

现在,对单个函数调用(而不是一次)评估是否创建空列表。

答案 1 :(得分:1)

a.append()i = 6不同。第一个更改数组但数组保持相同的对象(相同但不相等)。另一方面,后者为变量赋予一个全新的值。它不会改变任何对象(无论如何都不是可变的。)