这是我的Python代码:
my_constant = 5
my_constant_2 = 6
list_of_lists = [[3,2],[4,7]]
my_new_list = []
for i in list_of_lists:
my_dict = {}
for j in i:
if j > my_constant:
my_dict["a"] = "Hello"
my_dict["b"] = "Hello"
print(my_dict)
my_new_list.append(my_dict)
if j > my_constant_2:
my_dict["a"] = "Hello"
my_dict["b"] = "Bye"
print(my_dict)
my_new_list.append(my_dict)
print(my_new_list)
结果如下:
{'a': 'Hello', 'b': 'Hello'}
{'a': 'Hello', 'b': 'Bye'}
[{'a': 'Hello', 'b': 'Bye'}, {'a': 'Hello', 'b': 'Bye'}]
结果的前两行是根据我的预期,但第三行不是。我希望如此:
[{'a': 'Hello', 'b': 'Hello'}, {'a': 'Hello', 'b': 'Bye'}]
所以看起来当循环在追加到my_new_list之前等待第二个“if”时,我们这样的my_new_list会获得两倍于新的my_dict。
我知道下面的代码解决了这个问题(即在“if”中移动my_dict):
my_constant = 5
my_constant_2 = 6
list_of_lists = [[3,2],[4,7]]
my_new_list = []
for i in list_of_lists:
for j in i:
if j > my_constant:
my_dict = {}
my_dict["a"] = "Hello"
my_dict["b"] = "Hello"
print(my_dict)
my_new_list.append(my_dict)
if j > my_constant_2:
my_dict = {}
my_dict["a"] = "Hello"
my_dict["b"] = "Bye"
print(my_dict)
my_new_list.append(my_dict)
print(my_new_list)
但是,实际上my_dict不是空的,并且使用了一个函数来创建它(并且需要一些时间)。此外,还有更多的“ifs”,所以我不想使用上面的代码。
有没有办法克服它?
感谢。
答案 0 :(得分:1)
您一次又一次地重复使用同一个对象
使用deepcopy:
from copy import deepcopy
my_constant = 5
my_constant_2 = 6
list_of_lists = [[3,2],[4,7]]
my_new_list = []
for i in list_of_lists:
my_dict = {}
for j in i:
if j > my_constant:
my_dict["a"] = "Hello"
my_dict["b"] = "Hello"
print(my_dict)
my_new_list.append(deepcopy(my_dict))
if j > my_constant_2:
my_dict["a"] = "Hello"
my_dict["b"] = "Bye"
print(my_dict)
my_new_list.append(my_dict)
print(my_new_list)
输出:
{'b': 'Hello', 'a': 'Hello'}
{'b': 'Bye', 'a': 'Hello'}
[{'b': 'Hello', 'a': 'Hello'}, {'b': 'Bye', 'a': 'Hello'}]
为什么deepcopy()为什么不复制?
补充说明:
为了理解deepcopy vs copy,这里是示例代码:
让我们通过一个小例子来探讨你的问题:
所以假设你有一个清单:
a=['something']
还有第二个列表,其中包含:
list_1=[a,a,a]
所以当你这样做时:
a[0]="something_else"
您认为list_1
的输出是什么?
我们来看看:
a=['something']
list_1=[a,a,a]
a[0]="something_else"
print(list_1)
输出:
[['something_else'], ['something_else'], ['something_else']]
因为在python变量中没有存储值,变量只是引用对象而对象存储值所以在list_1中所有变量都指向同一个对象:
检查:
for i in list_1:
print(id(i))
输出:
4329477768
4329477768
4329477768
尝试深度扫描:
为什么
deepcopy
为什么不copy
?
假设你有这样的词:
dict_cell = {'item1': [20,34], 'item2': [25,9]}
您使用此dict_cell运行代码并获得输出:
[[{'item2': [25, 9], 'item1': 2}, {'item2': [25, 9], 'item1': [20, 34]}], [{'item2': [25, 9], 'item1': [20, 34]}, {'item2': [25, 9], 'item1': [20, 34]}]]
现在让我们尝试更改原始的dict值:
dict_cell = {'item1': [20,34], 'item2': [25,9]}
width = 2
height = 2
array = []
for i in range(height):
row=[]
for j in range(width):
row.append(dict_cell.copy())
array.append(row)
array[0][0]['item1'] =2
for key,value in dict_cell.items():
value[0]='changed'
print(array,'\n')
输出:
[[{'item1': 2, 'item2': ['changed', 9]}, {'item1': ['changed', 34], 'item2': ['changed', 9]}], [{'item1': ['changed', 34], 'item2': ['changed', 9]}, {'item1': ['changed', 34], 'item2': ['changed', 9]}]]
我们修改了orional dict但它改变了数组列表的dict中的内容,因为这是dict的浅层副本。它复制了dict但没有复制嵌套列表。
解决方案:
使用deepcopy。
答案 1 :(得分:1)
my_constant = 5
my_constant_2 = 6
list_of_lists = [[3,2],[4,7]]
my_new_list = []
for i in list_of_lists:
my_dict = {}
for j in i:
if j > my_constant:
my_dict["a"] = "Hello"
my_dict["b"] = "Hello"
print(my_dict)
my_new_list.append(my_dict.copy())
if j > my_constant_2:
my_dict["a"] = "Hello"
my_dict["b"] = "Bye"
print(my_dict)
my_new_list.append(my_dict.copy())
print(my_new_list)
因为在你的代码中,my_new_list [0]和my_new_list [1]是同一个对象。 所以当你改变my_dict时如果j> my_constant_2块,然后也将更改my_new_list [0]。 将对象添加到my_new_list时,请使用copy或deepcopy。 copy()函数将执行浅拷贝。 因此,为了安全起见,使用深度镜是很好的。
我认为my_dict初始化位置不合适。 请考虑一下。
答案 2 :(得分:0)
代码的两个版本之间的区别在于第一个代码将相同的dict多次附加到列表中。在这种情况下,列表将始终包含相同的dict。
但是,没有什么可以阻止您使用预先计算的值填充my_dict
:
defaults = {'some': 'common', 'values': 'here'}
for i in list_of_lists:
for j in i:
if j > my_constant:
my_dict = defaults.copy()
my_dict["a"] = "Hello"
my_dict["b"] = "Hello"
print(my_dict)
my_new_list.append(my_dict)
defaults
可以在循环内计算,如果它取决于i
或j
。
如果您担心数据重复,只需更改程序的逻辑,不要在my_new_list
中存储重复值。