Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

dict as class property seems to be same for all instances

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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?

>Solution :

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
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading