Qaerian
Qaerian

Reputation: 23

Values assigned differently in seemingly identical dictionaries

Somehow my two identical nested dictionaries (a dictionary containing dictionaries), created through different means, act differently when I try to assign a new value to a key.

d = {'a': {'item': None},'b': {'item': None},'c': {'item': None}}

The first dictionary is created manually, while the second one is created through this code:

data = {"item" : None}
keys = ["a","b","c"]
d2 = dict()
for i in range(len(keys)):
    d2[keys[i]] = data

Both of these give seemingly identical dictionaries.

print d
{'a': {'item': None}, 'c': {'item': None}, 'b': {'item': None}}
print d2
{'a': {'item': None}, 'c': {'item': None}, 'b': {'item': None}}

Everything seems good so far, but when I try to change the value of any of the keys, this happens:

d["a"]["item"] = "1"
d2["a"]["item"] = "1"
print d
{'a': {'item': '1'}, 'c': {'item': None}, 'b': {'item': None}}
print d2
{'a': {'item': '1'}, 'c': {'item': '1'}, 'b': {'item': '1'}}

I've tried everything I can think of and I can't find anyone that has had a similar problem. It just doesn't makes sense, why would it change the value in all three of the inside dictionaries? I hope you guys can help.
I'm using Python 2.7.5

Upvotes: 2

Views: 29

Answers (2)

Shahriar
Shahriar

Reputation: 13806

When you assign dict2 = dict1, you are not making a copy of dict1, it results in dict2 being just another name for dict1.

You can do this using deepcopy:

data = {"item" : None}
keys = ["a","b","c"]
d2 = dict()

for i in range(len(keys)):
    d2[keys[i]] =  copy.deepcopy(data)

But if you have data like :

data = {"item1" : None, "item2":{"Book":none}}

another dictionary inside your data dictionary, you must have to use deepcopy like above.

Otherwise, there are different way to copy your dict. Like

d2[keys[i]] =  copy.copy(data)
d2[keys[i]] =  dict(data)
d2[keys[i]] =  data.copy()

You can use any to copy your dict. Just use deepcopy when you have nested dict

Upvotes: 1

Jonas Byström
Jonas Byström

Reputation: 26129

You need to create a unique dict for each entry, like so:

keys = ["a","b","c"]
d2 = dict()
for i in range(len(keys)):
    d2[keys[i]] = {"item" : None}

Also you might prefer a more pythonic way:

>>> {k:{'item':None} for k in ['a','b','c']}
{'a': {'item': None}, 'c': {'item': None}, 'b': {'item': None}}

Upvotes: 4

Related Questions