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 instance variable being changed for all instances

I made a simple repro of my issue below. I have a class with an instance variable (inst_dict) which is of type dict. I also have a class variable (myClass_dict) which I use to keep track of each instance of my class.

What I am trying to do is update one value of inst_dict with a certain value. My problem is that it is updating the value for every instance.

Below is the code that almost does what I am aiming to do. The line inst.inst_dict = {"key1": i, "key2": "Val2"} sets the whole dict to the new value based on i. I am trying to just set one value in the dict, rather than the whole dict. The line after that is commented out is what I expected to work, where I access inst_dict for the current instance, then set the value of "key" to i.

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

When I run it with that line it updates the value of "key" in the dict, but for every instance. It’s like it gets changed to a class variable somewhere.

class My_Class(object):
    myClass_dict = {}

    def __init__(self, name,  inst_dict = {}):
        My_Class.myClass_dict[name] = self
        self.name = name
        self.inst_dict = inst_dict

for i in range(5):
    name = f'inst{i}'
    inst = My_Class(name)

    inst.inst_dict = {"key1": i, "key2": "Val2"}    #This works but changes the whole dict
    # inst.inst_dict['key'] = i   #This changes one value, but updates every instance
    print(name)

    for inst in My_Class.myClass_dict:
        print(f' {My_Class.myClass_dict[inst].name} {My_Class.myClass_dict[inst].inst_dict}')

Can somebody explain why this is updating every instance, and how I can avoid that?

Thanks!

edit:
Here is the output when running this with the first line (as written above):

inst0
 inst0 {'key1': 0, 'key2': 'Val2'}       
inst1
 inst0 {'key1': 0, 'key2': 'Val2'}       
 inst1 {'key1': 1, 'key2': 'Val2'}       
inst2
 inst0 {'key1': 0, 'key2': 'Val2'}       
 inst1 {'key1': 1, 'key2': 'Val2'}       
 inst2 {'key1': 2, 'key2': 'Val2'}       
inst3
 inst0 {'key1': 0, 'key2': 'Val2'}       
 inst1 {'key1': 1, 'key2': 'Val2'}       
 inst2 {'key1': 2, 'key2': 'Val2'}       
 inst3 {'key1': 3, 'key2': 'Val2'}       
inst4
 inst0 {'key1': 0, 'key2': 'Val2'}       
 inst1 {'key1': 1, 'key2': 'Val2'}       
 inst2 {'key1': 2, 'key2': 'Val2'}       
 inst3 {'key1': 3, 'key2': 'Val2'}       
 inst4 {'key1': 4, 'key2': 'Val2'}

As you can see, at each loop it updates the corresponding instance key1 to the value of i (0,1,2,3,4). And the value of key1 for inst0 remains unchanged in the following loops.

And here is when I comment that line, and uncomment the next line:

inst0
 inst0 {'key': 0}
inst1
 inst0 {'key': 1}
 inst1 {'key': 1}
inst2
 inst0 {'key': 2}
 inst1 {'key': 2}
 inst2 {'key': 2}
inst3
 inst0 {'key': 3}
 inst1 {'key': 3}
 inst2 {'key': 3}
 inst3 {'key': 3}
inst4
 inst0 {'key': 4}
 inst1 {'key': 4}
 inst2 {'key': 4}
 inst3 {'key': 4}
 inst4 {'key': 4}

As you can see, at each loop, it updates every instance that has been created. On the fourth loop, it not only updates inst4, but also inst 0 through 3.

>Solution :

Long story short: dict in python is mutable and therefore not advisible to be used as default value. See this post for example: Why is the empty dictionary a dangerous default value in Python?

The empty dict is constructed only once when defining the class and then every instance uses it – and updates it. EXCEPT for when you assign a whole new value: That works. If you want to have a "fresh" empty dict for every instance, the common construction is:

class My_Class(object):
    myClass_dict = {}

    def __init__(self, name,  inst_dict = None):
        My_Class.myClass_dict[name] = self
        self.name = name
        if inst_dict is not None:
            self.inst_dict = inst_dict
        else:
            self.inst_dict = {}
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