2

Possible Duplicate:
Why do attribute references act like this with Python inheritance?
Python: derived classes access dictionary of base class in the same memory location

Lets take the code:

class parent:
    book = {'one':1, 'two':2}

class child(parent):
    pass

first = child()
second = child()

print first.book
print second.book

second.book['one'] = 3

print first.book
print second.book

When you run this object 'first' has its dictionary edited! WTF? I thought 'first' and 'second' were separate instances of the 'child' class. What is happening here? Why does what you edit in second affect first?

I can 'fix' this by recreating book in each child class but thats not the right way to do it, I want to utilize classes the way they are meant to be used.

What am I doing wrong?

Btw my primary language is cpp so maybe i'm confusing cpp with python or something silly like that...

Any help would be greatly appreciated!

Community
  • 1
  • 1
Parad0x13
  • 2,007
  • 3
  • 23
  • 38

3 Answers3

2

You are declaring book as a static variable for the class parent. this means that the variable is initalised when the module is loaded.

You want to make it initialise when the class is created, hence you need the init method, which is a method which is automatically called when constructing each instance.

You also need to manually call the parent init.

class parent:
    def __init__(self):
        self.book = {'one':1, 'two':2}

class child(parent):
    def __init__(self):
        parent.__init__(self)

first = child()
second = child()

print first.book
print second.book

second.book['one'] = 3

print first.book
print second.book
Andrew Brock
  • 1,374
  • 8
  • 13
  • Thanks for including the childs constructor as well. I see that you have to explicitly declare you'd like to init the child with its parent's init as well. Fixed my bugs! – Parad0x13 Aug 26 '12 at 04:53
  • You don't need to explicitly call the child's constructor, no. It will be inherited like all attributes. – kindall Aug 26 '12 at 04:58
  • @kindall: I guess I should have been clearer. In this case, you don't but typically you will need to call the child constructor because you want to provide an overridden definition of it, and I was pointing out the fact that it will not call the constructor automatically as is the case in most other languages – Andrew Brock Aug 26 '12 at 05:05
2

To give each instance of the class it's own dictionary with the name book you would need to use the self notation.

class parent:
    def __init__(self):
        self.book = {'one':1, 'two':2}

class child(parent):
    pass

first = child()
second = child()

print first.book
print second.book

second.book['one'] = 3

print first.book
print second.book

Output:

>>> 
{'two': 2, 'one': 1}
{'two': 2, 'one': 1}
{'two': 2, 'one': 1}
{'two': 2, 'one': 3}
>>> 
chucksmash
  • 5,777
  • 1
  • 32
  • 41
1

Python initializes those class-scope variables when processing the class definition, and then the same object is used throughout.

If you want the dictionary to be unique to each instance, assign it during object construction by implementing __init__.

Platinum Azure
  • 45,269
  • 12
  • 110
  • 134