python 2.7中的staticmethod参数保留了跨调用的值?

时间:2012-04-20 00:29:27

标签: python

  

可能重复:
  “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)不是?我对这种行为感到很困惑。

由于

2 个答案:

答案 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

如果您了解可变性与不变性问题,请考虑类似的函数/方法:

  • 定义时,将分配默认参数值
  • 当它被调用时,正文被执行,如果它就地改变了可变的默认参数值,那么在每次后续调用中使用改变的值,其中默认参数值没有被覆盖,提供不同的值而不是它,