0

I have a question about inheritance in Python 2.7.

I have a two simple classes

class A():

    l = []

    def f(self):

        del self.l[:]

        if self.a == 'a':
            self.l.append('1')
        if self.a == 'b':
            self.l.append('2')


class B(A):

    def __init__(self, a):
        self.a = a

I create two instances of B in loop and call f() for set list 'l'

foo = ['a','b']
l = []

for x in foo:
    z = B(x)
    z.f()
    # normal result
    print z.l
    l.append(z)
print '-----'

for x in l:
    # strange result
    print x.l        

In result I get strange output:

Output:
['1']
['2']
-----
['2']
['2']
[Finished in 0.0s]

Instead 1,2; 1,2

Why is this happening?

I can fix it by define list "l" in def f(self)

class A():

    def f(self):

        l = []

        if self.a == 'a':
            self.l.append('1')
        if self.a == 'b':
            self.l.append('2')

In this case I get normal output, but still don't understand why this happens.

Thanks

Egregors
  • 403
  • 5
  • 10
  • As a side note: Do not use `class A():`. If this is Python 2.x, always always always use `class A(object):`, so you get new-style classes, especially when you're dealing with inheritance. If this is Python 3, it's less serious, because `class A:`, `class A():`, and `class A(object):` all mean the same thing—but the third is the most explicit, the first is the most compact and simple, and the one in the middle has neither advantage. – abarnert Sep 11 '14 at 04:32
  • Also: defining a class `A` that requires a member `self.a` which can only be set by a subclass is a bit of a strange thing. There are some cases where that makes sense, but in almost all of those cases, `A` is really either a mixin, or an [abstract base class](https://docs.python.org/2/library/abc.html), and if it's the latter, it's clearer (and useful for debugging) to define it that way. – abarnert Sep 11 '14 at 04:35

2 Answers2

0

In the first case, l is a class variable and this variable is shared by instances of the class.

In the second case, l is an instance variable, so each object has it's own variable.

Note that this has nothing to do with inheritance - you will see the same behaviour if instantiating either class A or B.

mhawke
  • 84,695
  • 9
  • 117
  • 138
0

The problem is that l isn't an instance variable, with each A (or B) instance having its own copy, it's a class variable, shared by all of the copies.

If you don't want a class variable, just don't define one. The same way you create self.a in B.__init__, create self.l in A.__init__.

abarnert
  • 354,177
  • 51
  • 601
  • 671