tags:

views:

120

answers:

2

The following code:

class House:
    links = []

class Link:
    pass

class Villa(House):
    pass

if __name__ == '__main__':
    house = House()
    villa = Villa()
    link = Link()
    house.links.append(link)

    print house.links
    print villa.links

results in this output:

[<__main__.Link instance at 0xb65a4b0c>] 
[<__main__.Link instance at 0xb65a4b0c>]

I find this very weird: Since it is another instance? - I would have expected that the output is - Since it is another instance?:

[<__main__.Link instance at 0xb65a4b0c>] 
[]

When changing the line house.links.append(link) to house.links = [link] everything works as expected.

Can somebody explain this behavior?

+19  A: 

It is another instance, but you have defined links as a class variable rather than an instance variable.

An instance variable would be defined as such:

class House(object):  # Always use new-style classes except for backward compatibility
  def __init__(self):
    self.links = []

Note that in Python, unlike other languages, an instance variable is explicitly declared to be a property of an instance. This usually happens in the __init__ method, to ensure that every instance has the variable.

Then, the subclass would look like this:

class Villa(House):
  def __init__(self):
    super(Villa, self).__init__()

And executing your code gives the correct results:

>>> house = House()
>>> villa = Villa()
>>> link = Link()
>>> house.links.append(link)
>>> print house.links
[<__main__.Link instance at 0xcbaa8>]
>>> print villa.links
[]
danben
+3  A: 

In your code, links is an attribute on the class, making it shared by all instances of that class:

class House:
    links = []

Because of this, your Villa class shares this attribute, because an instance of Villa is (as a subclass) also an instance of House.

If you want to make links an instance variable, write a constructor and set links as an attribute of self, e.g.

class House:
    def __init__(self):
        self.links = []
Eli Courtwright