Reputation: 97
For the needs of the project im iterating over some data and adding needed values to premade dictionary.
here is striped down example of code which represents my question:
class Parser:
def __init__(self):
self.records = [['value1','value2','value3'],
['value4','value5','value6'],
['value7','value8','value9']]
def get_parsed(self):
parsed = []
dic = {'key1': '',
'key2': '',
'key3': '',
}
for i in self.records:
dic['key1'] = i[0]
dic['key2'] = i[1]
dic['key3'] = i[2]
parsed.append(dic)
return parsed
What i expect to get is list of dicts like this:
[{'key1':'value1','key2':'value2','key3':'value3'},
{'key1':'value4','key2':'value5','key3':'value6'},
{'key1':'value7','key2':'value8','key3':'value9'}]
But what im getting is:
[{'key1':'value1','key2':'value2','key3':'value3'},
{'key1':'value1','key2':'value2','key3':'value3'},
{'key1':'value1','key2':'value2','key3':'value3'}]
Though if i move dictionary initialization into 'for' loop - im getting the desired result but i don't understand why is that happening?
EDIT: The question is more "Why does it happens this way" I did some testing in ipython and that's what i've got:
In [1]: d = {'a':'','b':'','c':''}
In [2]: d
Out[2]: {'a': '', 'b': '', 'c': ''}
In [3]: d['a'] = 'value'
In [4]: d['b'] = 'other_value'
In [5]: d['c'] = 'third_value'
In [6]: d
Out[6]: {'a': 'value', 'b': 'other_value', 'c': 'third_value'}
In [7]: d['a'] = 'inserting new value'
In [8]: d
Out[8]: {'a': 'inserting new value', 'b': 'other_value', 'c': 'third_value'}
So the value of the key could be updated and it changes, why doesn't it happen in FOR loop?
Upvotes: 4
Views: 9416
Reputation: 251598
Because your dic
is created outside the loop, you only create one dict. If you want three different dicts, you need to create three different dicts, so move the initial creation of dic
inside the loop.
To answer your updated question, the issue is that although you think you are appending a new dict with each parsed.append(dic)
, you are just appending the same dict three times. Append
doesn't copy the dict. So whenever you modify that dict, all the dicts in parse
show the change, since they are all the same dict. This version of your second code example may be more illustrative:
>>> d = {'a': '', 'b': '', 'c': ''}
>>> stuff = []
>>> stuff.append(d)
>>> print stuff
[{'a': '', 'c': '', 'b': ''}]
>>> d['a'] = 'other'
>>> print stuff
[{'a': 'other', 'c': '', 'b': ''}]
>>> stuff.append(d)
>>> print stuff
[{'a': 'other', 'c': '', 'b': ''}, {'a': 'other', 'c': '', 'b': ''}]
>>> d['a'] = 'yet another'
>>> print stuff
[{'a': 'yet another', 'c': '', 'b': ''}, {'a': 'yet another', 'c': '', 'b': ''}]
Notice that changing the dict "works" in that it indeed changes the value, but regardless of that, the list still contains the same dict multiple times, so any changes you make overwrite whatever changes you made earlier. In the end, your list only contains the last version of the dict, because all earlier changes were overwritten in all dicts in the list.
Upvotes: 6
Reputation: 839194
You are modifying and inserting the same dictionary to your list three times. Create a new dictionary for each iteration of the loop:
for i in self.records:
dic = { 'key1': i[0], 'key2': i[1], 'key3': i[2] }
parsed.append(dic)
Upvotes: 6