可能重复:
“Least Astonishment” in Python: The Mutable Default Argument
使用python 2.7我遇到了奇怪的行为,我不知道如何解释它或者它是否存在于任何python文档中。使用代码
class MyClass:
@staticmethod
def func(objects=[], a=None, b=None):
objects.append(a)
print 'objects: %s'%objects
print 'b: %s'%b
MyClass.func(a='one')
MyClass.func(a='two', b='foo')
MyClass.func(a='three')
我得到了get输出
objects: ['one']
b: None
objects: ['one', 'two']
b: foo
objects: ['one', 'two', 'three']
b: None
正如您所看到的,该方法的第一个列表参数(对象)在调用之间保留了它的值。新值被附加到最后一个列表,即使在它的头部声明中它具有默认值[]。但是最后一个参数(b)没有保留它的值,它被重置为调用之间的默认值。
预期(对我而言)是对象参数应该在任何方法调用时重置为默认值(比如b参数),但这似乎不会发生,而且似乎只发生在第一次打电话
任何人都可以解释这种行为吗?它是这个版本的python中的错误还是预期的行为?可能与调用中保留的列表引用有关,但字符串变量(b)不是?我对这种行为感到很困惑。
由于
答案 0 :(得分:3)
与静态方法无关。这是Python中一个非常常见的错误。
Python中的函数是第一类对象,而不仅仅是代码块,因此分配给参数中对象的空列表是附加到函数对象的真实列表。每次调用它并将某些内容附加到该列表时,您使用的是相同的列表。很容易看到它以这种方式发生:
>>> def func(x, objects=[]):
... objects.append(x)
...
>>> func(1)
>>> func.func_defaults
([1],)
>>> func(2)
>>> func.func_defaults
([1, 2],)
>>> func(3)
>>> func.func_defaults
([1, 2, 3],)
func_defaults是函数对象属性,它构成您设置的默认关键字参数。看看列表是如何变化的?
做你想做的事的正确方法是:
class MyClass:
@staticmethod
def func(objects=None, a=None, b=None):
if objects is None:
objects = []
objects.append(a)
print 'objects: %s'%objects
print 'b: %s'%b
答案 1 :(得分:1)
这种行为广为人知,被许多人视为一种功能,并不是特定于静态方法的。它适用于所有功能。 当您将可变对象指定为参数的默认值时,会发生这种情况。
在StackOverflow上查看此答案:Default Argument Gotchas / Dangers of Mutable Default arguments
如果您了解可变性与不变性问题,请考虑类似的函数/方法: