Reputation: 1260
I recognize strange behavior in my code. I extract some testcode to demonstrate:
class A:
def __init__(self):
super().__init__()
self.mystr = 'A'
self.mydict['key'] = 'value'
class B(A):
mystr = 'B'
mydict = {}
def __init__(self, name):
print(name, 'mystr (before)', self.mystr)
print(name, 'mydict (before)', self.mydict)
super().__init__()
print(name, 'mystr (after)', self.mystr)
print(name, 'mydict (after)', self.mydict)
if __name__ == '__main__':
b1 = B('b1')
b2 = B('b2')
The output is:
b1 mystr (before) B
b1 mydict (before) {}
b1 mystr (after) A
b1 mydict (after) {'key': 'value'}
b2 mystr (before) B
b2 mydict (before) {'key': 'value'} // <- I expect this to be {}
b2 mystr (after) A
b2 mydict (after) {'key': 'value'}
The property mystr
works as I expected. For the second instance b2
it is 'B' as it was initialized. But the property mydict
is not initialized correct for the second instance and contains the key/value pair:
b2 mydict (before) {'key': 'value'}
I know that there a mutable and immutable variables in Python and that the first one are hold by reference. But I can explain, why my code is not working as expected.
Can somebody give me a hint?
Upvotes: 0
Views: 42
Reputation: 531055
Yes, you have a single dict shared by all instance of the class. The key is that
self.mydict['key'] = 'value'
is not an assignment to the attribute mydict
, so it does not create a new instance attribute. Rather, it's a method call
self.mydict.__setitem__('key', 'value')
and the lookup self.mydict
resolves to A.mydict
since there is no instance attribute named mydict
.
On the other hand,
self.mystr = 'A'
is an assignment to an attribute, so it always creates a new instance attribute if it does not already exist, rather than changing the value of an existing class attribute of the same name. If you want to change the value of a class attribute via an instance of the class, you have to first get a reference to the class, with something like
self.__class__.mystr = 'A' # Modifies A.mystr without creating self.mystr instead
Upvotes: 1