Values of instance variables of superclass persist

2019-06-23 19:14发布

I'm not sure if this is a fundamental misunderstanding on my part of the way that OOP in Python works, but I'm seeing some extremely strange behavior. Here's a code snippet:

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

I expect that when bar2 is constructed, its mylist instance variable will be set to the empty list. However, when I run this program in Python 2.6.6, I get the following output:

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

It looks like Foo's mylist instance variable is being persisted across multiple instances of the Bar class, but I have no idea why that would be. Any help you guys could give me would be greatly appreciated.

标签: python oop
2条回答
We Are One
2楼-- · 2019-06-23 19:32

Take a loot at Python tutorial on default argument values It says:

Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes.

or example, the following function accumulates the arguments passed to it on subsequent calls:

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

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

This will print

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

If you don’t want the default to be shared between subsequent calls, you can write the function like this instead:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L
查看更多
你好瞎i
3楼-- · 2019-06-23 19:40

The problem is that default parameters are bound at module initialization time, not at function invocation time, so there is only one default list that gets shared as the default for all invocations of that function.

What you really want to do is:

def __init__(self, l=None):
    if l is None:
        l = []
    self.mylist = l
查看更多
登录 后发表回答