超类的实例变量的值在子类的实例之间持久存在

时间:2011-04-06 04:00:43

标签: python oop

我不确定这是否是我对Python中OOP工作方式的基本误解,但我看到了一些非常奇怪的行为。这是一段代码:

class Foo(object):
    def __init__(self, l = []):
        print "Foo1:", l
        self.mylist = l
        print "Foo2:", self.mylist

class Bar(Foo):
    def __init__(self, label=None):

        self.label = label
        super(Bar, self).__init__()
        print "Bar:", self.mylist



bar1 = Bar()
bar1.mylist.append(4)

bar2 = Bar()
print "bar2's list:", bar2.mylist

我希望在构造bar2时,其mylist实例变量将被设置为空列表。但是,当我在Python 2.6.6中运行此程序时,我得到以下输出:

Foo1: []
Foo2: []
Bar: []
Foo1: [4]
Foo2: [4]
Bar: [4]
bar2's list: [4]

看起来Foo的mylist实例变量被保存在Bar类的多个实例中,但我不知道为什么会这样。我们非常感谢你们给予我的任何帮助。

2 个答案:

答案 0 :(得分:6)

问题是默认参数在模块初始化时绑定,而不是在函数调用时绑定,因此只有一个默认列表作为该函数的所有调用的默认值共享。

你真正想做的是:

def __init__(self, l=None):
    if l is None:
        l = []
    self.mylist = l

答案 1 :(得分:2)

Python tutorial on default argument values抓一个战利品 它说:

  

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

或者示例,以下函数累积在后续调用中传递给它的参数:

def f(a, L=[]):
    L.append(a)
    return L

print f(1)
print f(2)
print f(3)

这将打印

[1]
[1, 2]
[1, 2, 3]

如果您不希望在后续调用之间共享默认值,则可以编写如下函数:

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