1

可能的重复:
Python 中的“Least Astonishment”:可变默认参数

当我阅读以下讲义时: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背景,这里不是a_list局部变量吗?它如何将其值从一个函数调用存储到另一个函数?此外,有人可以详细说明为什么第二个例子比第一个更好吗?在定义中定义函数有什么问题?它似乎没有覆盖原始值或任何东西。

谢谢!

4

1 回答 1

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 的出色解释

于 2012-08-30T13:41:31.187 回答