Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning value to nested dictionary is applied inappropriately to all keys

Essentially I'm trying to assign a value to a nested dictionary. If I build the dictionary by spelling it out, then later assigning a value works as expected. However if I create a template dictionary, assign that to all the keys, then later go back and try and assign a value to a nested key, now EVERY instance of that key gets that value. Easier to show with code:

initialize_dict = {'a':0,'b':0}
x = {}
x['FOO'] = initialize_dict
x['BAR'] = initialize_dict

y = {'FOO':{'a':0,'b':0},'BAR':{'a':0,'b':0}}

logging.info("x is {}".format(x))
logging.info("y is {}".format(y))
logging.info(x==y)

x['FOO']['a']=13231
y['FOO']['a']=13231

logging.info("new x is {}".format(x))
logging.info("new y is {}".format(y))

And my log:

INFO:root:x is {'FOO': {'a': 0, 'b': 0}, 'BAR': {'a': 0, 'b': 0}}
INFO:root:y is {'FOO': {'a': 0, 'b': 0}, 'BAR': {'a': 0, 'b': 0}}
INFO:root:True
INFO:root:new x is {'FOO': {'a': 13231, 'b': 0}, 'BAR': {'a': 13231, 'b': 0}}
INFO:root:new y is {'FOO': {'a': 13231, 'b': 0}, 'BAR': {'a': 0, 'b': 0}}

As you can see, for some reason the value 13231 is being assigned in x to ['FOO']['a'] AND ['BAR']['a'] if I build it using a template, but if I had written out the full dictionary to begin with (in y). I test above to make sure that x and y are truly equivalent before trying to assign any values.

like image 488
SS Shah Avatar asked Oct 15 '25 15:10

SS Shah


1 Answers

In Python, when you assign a variable you are binding a name to some object. In this case x['FOO'] and x['BAR'] are names that are both bound to the same object. When you change x['FOO']['a'] you are changing the key 'a' in the single object, that both x['FOO'] and x['BAR'] refer to.

When you assign a value to x['FOO']['a'] you are changing the value of x['FOO']['a'], x['BAR']['a'], and also initialize_dict['a'].

To fix this problem you just need to to have x['FOO'] and x['BAR'] refer to a copy of initialize_dict so that each one can be changed independently:

initialize_dict = {'a':0,'b':0}
x = {}
x['FOO'] = initialize_dict.copy()  # Make copies of the dictionary.
x['BAR'] = initialize_dict.copy()  #

y = {'FOO':{'a':0,'b':0},'BAR':{'a':0,'b':0}}

print("x is {}".format(x))
print("y is {}".format(y))
print(x==y)

x['FOO']['a']=13231
y['FOO']['a']=13231

print("new x is {}".format(x))
print("new y is {}".format(y))
like image 123
jeremye Avatar answered Oct 17 '25 04:10

jeremye



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!