dict在迭代期间改变了大小,但没有在Python中编辑它

时间:2017-08-16 12:02:57

标签: python dictionary

我在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]

我忽略了什么吗?

3 个答案:

答案 0 :(得分:3)

您正在复制字典,但使用浅拷贝

由于您在子字典上进行了迭代(没有复制,arrtest之间的引用相同),您会收到此错误。

使用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.copydict.copy仅创建浅拷贝!

Docs for 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]

Try it online!

一些阅读:How to avoid "RuntimeError: dictionary changed size during iteration" error?