为了项目的需要,我迭代一些数据并将所需的值添加到预制字典中。
这是代表我的问题的代码示例:
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
我期望得到的是像这样的词典:
[{'key1':'value1','key2':'value2','key3':'value3'},
{'key1':'value4','key2':'value5','key3':'value6'},
{'key1':'value7','key2':'value8','key3':'value9'}]
但是我得到的是:
[{'key1':'value1','key2':'value2','key3':'value3'},
{'key1':'value1','key2':'value2','key3':'value3'},
{'key1':'value1','key2':'value2','key3':'value3'}]
虽然如果我将字典初始化移动到'for'循环 - 我得到了所需的结果,但我不明白为什么会发生这种情况?
编辑: 问题是“为什么会这样发生” 我在ipython中做了一些测试,这就是我所拥有的:
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'}
因此密钥的价值可以更新,更改,为什么不在FOR循环中发生?
答案 0 :(得分:5)
您正在修改相同的词典并将其插入列表三次。为循环的每次迭代创建新词典:
for i in self.records:
dic = { 'key1': i[0], 'key2': i[1], 'key3': i[2] }
parsed.append(dic)
答案 1 :(得分:5)
因为你的dic
是在循环之外创建的,所以你只创建一个dict。如果你想要三个不同的dicts,你需要创建三个不同的dicts,所以在循环中移动dic
的初始创建。
要回答您更新的问题,问题在于,虽然您认为每个parsed.append(dic)
附加一个新的字典,但您只需要添加三次相同的字典。 Append
不会复制该词典。因此,无论何时修改该字典,parse
中的所有字母都会显示更改,因为它们都是相同的字典。这个版本的第二个代码示例可能更具说明性:
>>> 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': ''}]
请注意,更改dict“有效”,因为它确实会更改值,但无论如何,列表仍会多次包含相同的dict,因此您所做的任何更改都会覆盖您之前所做的任何更改。最后,您的列表仅包含dict的最后一个版本,因为所有先前的更改都被覆盖在列表中的所有dicts中。