参数值正确性

时间:2012-08-30 13:27:05

标签: python list

  

可能重复:
  “Least Astonishment” in Python: The Mutable Default Argument

当我阅读以下讲义时:http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables

我遇到了以下示例。基本上,它声称:

def bad_append(new_item, a_list=[]):
    a_list.append(new_item)
    return a_list

不是将项目附加到列表的最佳方式,因为在函数定义时评估a_list

相反,更好的选择是:

def good_append(new_item, a_list=None):
    if a_list is None:
        a_list = []
    a_list.append(new_item)
    return a_list

因为它在函数的运行时定义变量。

来自C-background,这里不是a_list一个局部变量?它如何将其值从一个函数调用存储到另一个函数调用?此外,有人可以详细说明为什么第二个例子比第一个更好?在定义中定义函数有什么问题?它似乎不会覆盖原始值或任何东西。

谢谢!

1 个答案:

答案 0 :(得分:2)

一个简单的答案是def语句创建一个对象,并且在对象执行时(执行def行时),创建一个新的列表对象并附加到该对象(在这种情况下,对象是一个函数)。

在后续执行时 - 您可能期望的是生成新列表;但实际上,在首次运行函数定义时创建的同一对象仍然存在;并且该对象的所有“成员”保持不变。这就是它不断添加到同一列表的原因。

它被认为是错误的原因是因为你可能期望参数(在每次执行时,生成一个新列表)不是语句所做的。这就是为什么更好的模式是传递None或其他一些空白对象。

请考虑以下事项:

>>> bad_append('foo')
['foo']
>>> bad_append('bar')
['foo', 'bar']
>>> bad_append('zoo')
['foo', 'bar', 'zoo']
>>> bad_append('bar',[])
['bar']
>>> bad_append('bar') # what?
['foo', 'bar', 'zoo', 'bar']

正如你所看到的那样,当我传入一个新列表时,在下一次执行时它并没有留下来;而是执行 def 时构建的原始列表仍然存在。

有关详细信息,请参阅effbot的this excellent explanation