我在Python中遇到dict changed size during iteration
错误,即使我没有改变嵌套的dict。我正在删除原文,而不是我正在循环的副本
test = arr.copy()
for map in test:
for mID in test[map]: #here is dictionary changed size during iteration
v = test[map][mID]['val']
if v < 1:
del arr[map][mID]
我忽略了什么吗?
答案 0 :(得分:3)
您正在复制字典,但使用浅拷贝。
由于您在子字典上进行了迭代(没有复制,arr
和test
之间的引用相同),您会收到此错误。
使用deepcopy
模块的copy
功能,如下所示:
import copy
test = copy.deepcopy(arr)
但是,深度复制对象对于这样的问题来说是过度的。你可以迭代这样的项目的副本(也是:总是迭代键+值,所以你不必通过循环中的键访问值):
for map,map_values in arr.items():
for mID,subdict in list(map_values.items()): # make a copy/force iteration using `list`
v = subdict['val']
if v < 1:
del map_values[mID]
答案 1 :(得分:1)
如果您正在使用嵌套dicts,则应创建深层副本。
import copy
test = copy.deepcopy(arr)
请注意,copy.copy
和dict.copy
仅创建浅拷贝!
返回字典的浅表副本。
答案 2 :(得分:1)
其他答案是正确的:copy()
会返回字典的浅表副本,因此arr[map]
将是test[map]
的副本,但arr[map][mID]
和{{1} }将完全arr[map][mID]
。
以下架构显示了这种情况:
test[map][mID]
当您尝试删除arr -+-> 'map1' -+-> { 'id1':{'val':0}, ... }
| |
+-> 'map2' ---+-> { 'id1':{'val':2}, ... }
| |
test -+-> 'map1' -+ |
| |
+-> 'map2' ---+
时,您也尝试删除arr['map1']['id1']
,但您正在迭代test['map1']['id1']
。这就是您收到此错误的原因(test['map1']
的大小在您迭代时可能不会改变。)
但我不认为test['map1']
是一个很好的解决方案。您需要的只是复制deepcopy
的密钥并迭代此副本。
arr[map]
一些阅读:How to avoid "RuntimeError: dictionary changed size during iteration" error?