英文:
Why do my previous dictionaries in a list change when I try to add a new one?
问题
I have a code that does the following:
遍历一个字典列表,使用每个字典的数据填充一个"临时"字典,然后将"临时"字典附加到一个"信息"列表中。
However, I've noticed that every time the "temporary" dictionary changes, the overall "information" list changes as well.
然而,我注意到每当"临时"字典发生变化时,整个"信息"列表也会发生变化。
This is a test code that perfectly represents the issue that I'm having:
这是一个完美表示我遇到问题的测试代码:
dict1 = {"Name":"Maria", "Age":"22"}
dict2 = {"Name":"Ryley", "Age":"23"}
dict3 = {"Name":"Helen", "Age":"24"}
all_dicts = [dict1, dict2, dict3]
temp_dict ={}
info = []
for dict in all_dicts:
print ("CURRENT DICT: " + dict["Name"])
print ("Info before loop: " + str(info))
# Temporary loop.
for key in dict:
temp_dict[key] = dict[key]
print ("Info after loop: " + str(info))
info.append(temp_dict)
When this is run, the "info" variable is different before and after the "temporary loop" despite the fact that it's the "temp_dict" variable that is changing. This is the output:
运行此代码后,"info"变量在"临时循环"之前和之后是不同的,尽管"temp_dict"变量发生了变化。以下是输出:
CURRENT DICT: Maria
Info before loop: []
Info after loop: []
CURRENT DICT: Ryley
Info before loop: [{'Name': 'Maria', 'Age': '22'}]
Info after loop: [{'Name': 'Ryley', 'Age': '23'}, {'Name': 'Ryley', 'Age': '23'}]
CURRENT DICT: Helen
Info before loop: [{'Name': 'Ryley', 'Age': '23'}, {'Name': 'Ryley', 'Age': '23'}]
Info after loop: [{'Name': 'Helen', 'Age': '24'}, {'Name': 'Helen', 'Age': '24'}]
I understand that the way to fix this would be to replace the "temporary loop" with this:
我理解修复这个问题的方法是将"临时循环"替换为:
temp_dict = dict
But I would really like to understand why this is happening. The line above and the "temporary loop" should virtually be doing the same thing, so why is the "info" variable changing retroactively as the "temp_dict" variable does? Is there a way to prevent this besides my solution above?
但我真的很想理解为什么会发生这种情况。上面的代码行和"临时循环"实际上应该是在做同样的事情,那么为什么"info"变量会随着"temp_dict"变量的变化而追溯性地发生变化呢?除了我上面提到的解决方法之外,是否还有其他方法可以防止这种情况发生?
英文:
I have a code that does the following:
Goes through a list of dictionaries, fills up a "temporary" dictionary with each one's data, and then appends the "temporary" dictionary to an "information" list.
However, I've noticed that every time the "temporary" dictionary changes, the overall "information" list changes as well.
This is a test code that perfectly represents the issue that I'm having:
dict1 = {"Name":"Maria", "Age":"22"}
dict2 = {"Name":"Ryley", "Age":"23"}
dict3 = {"Name":"Helen", "Age":"24"}
all_dicts = [dict1, dict2, dict3]
temp_dict ={}
info = []
for dict in all_dicts:
print ("CURRENT DICT: " + dict["Name"])
print ("Info before loop: " + str(info))
#Temporary loop.
for key in dict:
temp_dict[key] = dict[key]
print ("Info after loop: " + str(info))
info.append(temp_dict)
When this is run, the "info" variable is different before and after the "temporary loop" despite the fact that it's the "temp_dict" variable that is changing. This is the output:
CURRENT DICT: Maria
Info before loop: []
Info after loop: []
CURRENT DICT: Ryley
Info before loop: [{'Name': 'Maria', 'Age': '22'}]
Info after loop: [{'Name': 'Ryley', 'Age': '23'}]
CURRENT DICT: Helen
Info before loop: [{'Name': 'Ryley', 'Age': '23'}, {'Name': 'Ryley', 'Age': '23'}]
Info after loop: [{'Name': 'Helen', 'Age': '24'}, {'Name': 'Helen', 'Age': '24'}]
I understand that the way to fix this would be to replace the "temporary loop" with this:
temp_dict = dict
But I would really like to understand why this is happening. The line above and the "temporary loop" should virtually be doing the same thing, so why is the "info" variable changing retroactively as the "temp_dict" variable does? Is there a way to prevent this besides my solution above?
答案1
得分: 0
在循环外创建的temp_dict
会导致在循环内不断更新和追加同一个字典到info
中。每次临时循环运行时,都会更改列表中多次引用的同一个字典。
解决方法是在循环内创建temp_dict
。同时,在将字典添加到info
之前,打印"循环后的信息",以避免遗漏在内部循环中刚刚构建的数据。
dict1 = {"Name":"Maria", "Age":"22"}
dict2 = {"Name":"Ryley", "Age":"23"}
dict3 = {"Name":"Helen", "Age":"24"}
all_dicts = [dict1, dict2, dict3]
info = []
for dict in all_dicts:
temp_dict ={}
print ("当前字典: " + dict["Name"])
print ("循环前信息: " + str(info))
#临时循环
for key in dict:
temp_dict[key] = dict[key]
info.append(temp_dict)
print ("循环后信息: " + str(info))
输出结果
当前字典: Maria
循环前信息: []
循环后信息: [{'Name': 'Maria', 'Age': '22'}]
当前字典: Ryley
循环前信息: [{'Name': 'Maria', 'Age': '22'}]
循环后信息: [{'Name': 'Maria', 'Age': '22'}, {'Name': 'Ryley', 'Age': '23'}]
当前字典: Helen
循环前信息: [{'Name': 'Maria', 'Age': '22'}, {'Name': 'Ryley', 'Age': '23'}]
循环后信息: [{'Name': 'Maria', 'Age': '22'}, {'Name': 'Ryley', 'Age': '23'}, {'Name': 'Helen', 'Age': '24'}]
值得注意的是,你可以用更少的步骤完成这个操作:
dict1 = {"Name":"Maria", "Age":"22"}
dict2 = {"Name":"Ryley", "Age":"23"}
dict3 = {"Name":"Helen", "Age":"24"}
all_dicts = [dict1, dict2, dict3]
info = [d.copy() for d in all_dicts]
英文:
The problem is that you create a single temp_dict
outside of the loop and keep updating and appending that one dict to info
. With each run of the temporary loop, you are changing the single dict that is referenced multiple times in the list.
The solution is to create temp_dict
in the loop. You also print "Info after loop" before adding the dict to info
, missing the data you just built up in the inner loop.
dict1 = {"Name":"Maria", "Age":"22"}
dict2 = {"Name":"Ryley", "Age":"23"}
dict3 = {"Name":"Helen", "Age":"24"}
all_dicts = [dict1, dict2, dict3]
info = []
for dict in all_dicts:
temp_dict ={}
print ("CURRENT DICT: " + dict["Name"])
print ("Info before loop: " + str(info))
#Temporary loop.
for key in dict:
temp_dict[key] = dict[key]
info.append(temp_dict)
print ("Info after loop: " + str(info))
outputs
CURRENT DICT: Maria
Info before loop: []
Info after loop: [{'Name': 'Maria', 'Age': '22'}]
CURRENT DICT: Ryley
Info before loop: [{'Name': 'Maria', 'Age': '22'}]
Info after loop: [{'Name': 'Maria', 'Age': '22'}, {'Name': 'Ryley', 'Age': '23'}]
CURRENT DICT: Helen
Info before loop: [{'Name': 'Maria', 'Age': '22'}, {'Name': 'Ryley', 'Age': '23'}]
Info after loop: [{'Name': 'Maria', 'Age': '22'}, {'Name': 'Ryley', 'Age': '23'}, {'Name': 'Helen', 'Age': '24'}]
To note, you can do this in fewer steps
dict1 = {"Name":"Maria", "Age":"22"}
dict2 = {"Name":"Ryley", "Age":"23"}
dict3 = {"Name":"Helen", "Age":"24"}
all_dicts = [dict1, dict2, dict3]
info = [d.copy() for d in all_dicts]
答案2
得分: 0
这是关于引用变量而不是复制它的情况。如果你不了解这一点,就像你的新变量指向旧变量而不是创建一个独立的副本一样,所以每当你对旧变量进行更改,因为新变量只是指向旧变量,如果你打印它,它会显示更改,尽管你没有明确对新变量进行任何更改,为了避免这种情况,你必须创建旧变量的实际副本,换句话说,这就是所谓的“深拷贝”,而引用则被称为“浅拷贝”,你可以阅读相关资料,这是一种与编程语言无关的概念,所以无论你使用哪种编程语言,几乎都存在。
所以这是一个解决方案,导入复制库:
import copy
并将最后一行更改为:
info.append(copy.deepcopy(temp_dict))
这里的 copy.deepcopy
返回了 temp_dict
的独立副本,所以现在你可以更改 temp_dict
而不影响 info
数组中的字典。
英文:
It is the case of referencing a variable instead copying it. If you are not aware of it, it is like your new variable points to the old variable instead of making an independent copy, so whenever you make changes in the old variable because the new variable just points to the old one if you print it, it will show the changes however you haven't made any changes in new variable explicitly, to avoid this you have to make an actual copy of the old variable, in other words, it is known as 'Deep Copy' and referencing is known as 'shallow copy' you can read on it, it is language independent concept so no matter which language you are using it there almost in every programming language.
So here is a solution,
import the copy library
import copy
and change last line to
info.append(copy.deepcopy(temp_dict))
here copy.deepcopy returns an independent copy of temp_dict so now you can change the temp_dict without changing the dict present in info
array
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论