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

dict在迭代期间更改了大小,但没有在Python中编辑它,python,dictionary,Python,Dictionary,在Python的迭代错误期间,我得到了dict更改的大小,即使我没有更改嵌套的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: d

在Python的迭代错误期间,我得到了dict更改的大小,即使我没有更改嵌套的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]

我忽略了什么吗?

你在抄字典,但用的是浅显的抄本

由于您在未复制的子目录上进行迭代,因此arr和test之间的引用相同,因此会出现此错误

使用复制模块的deepcopy功能,如下所示:

import copy
test = copy.deepcopy(arr)
然而,对于这样的问题,深度复制对象是过分的。您也可以这样迭代项的副本:始终迭代key+值,这样就不必在循环中按键访问值:

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]

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

由于您在未复制的子目录上进行迭代,因此arr和test之间的引用相同,因此会出现此错误

使用复制模块的deepcopy功能,如下所示:

import copy
test = copy.deepcopy(arr)
然而,对于这样的问题,深度复制对象是过分的。您也可以这样迭代项的副本:始终迭代key+值,这样就不必在循环中按键访问值:

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]

如果使用嵌套的dict,则应创建深度副本

import copy
test = copy.deepcopy(arr)
请注意,copy.copy和dict.copy仅创建浅拷贝

:

返回字典的浅显副本


如果使用嵌套的dict,则应创建深度副本

import copy
test = copy.deepcopy(arr)
请注意,copy.copy和dict.copy仅创建浅拷贝

:

返回字典的浅显副本


其他答案是正确的:copy返回字典的浅层副本,因此arr[map]将是test[map]的副本,但arr[map][mID]和arr[map][mID]将恰好是test[map][mID]

以下模式显示了这种情况:

arr  -+-> 'map1' -+-> { 'id1':{'val':0}, ... }
      |           |
      +-> 'map2' ---+-> { 'id1':{'val':2}, ... }
                  | |
test -+-> 'map1' -+ |
      |             |
      +-> 'map2' ---+
当您尝试删除arr['map1']['id1']时,您也尝试删除测试['map1']['id1'],但您正在测试['map1']上迭代。这就是为什么您会遇到这个错误,当您在测试['map1'上迭代时,它的大小可能不会改变

但我不认为deepcopy是好的解决方案。您所需要的只是复制arr[map]的键并在该副本上迭代

for map in arr:
    for mID in list(arr[map]): # here's the copy of the keys
        v = arr[map][mID]['val']
        if v < 1:
            del arr[map][mID] # allowed because you are not iterating on the dict, but on the copy of the keys

一些阅读:

其他答案是正确的:copy返回字典的浅副本,因此arr[map]将是test[map]的副本,但是arr[map][mID]和arr[map][mID]将恰好是test[map][mID]

以下模式显示了这种情况:

arr  -+-> 'map1' -+-> { 'id1':{'val':0}, ... }
      |           |
      +-> 'map2' ---+-> { 'id1':{'val':2}, ... }
                  | |
test -+-> 'map1' -+ |
      |             |
      +-> 'map2' ---+
当您尝试删除arr['map1']['id1']时,您也尝试删除测试['map1']['id1'],但您正在测试['map1']上迭代。这就是为什么您会遇到这个错误,当您在测试['map1'上迭代时,它的大小可能不会改变

但我不认为deepcopy是好的解决方案。您所需要的只是复制arr[map]的键并在该副本上迭代

for map in arr:
    for mID in list(arr[map]): # here's the copy of the keys
        v = arr[map][mID]['val']
        if v < 1:
            del arr[map][mID] # allowed because you are not iterating on the dict, but on the copy of the keys

一些阅读:

对于嵌套的数据结构,您需要使用copy.deepcopy而不是copy。不需要复制整个dict-只需迭代一个键的副本,即使用listtest和listtest[map]。@ekhumoro您说得对!我已经更新了我的答案。对于嵌套的数据结构,您需要使用copy.deepcopy而不是copy。无需复制整个dict-只需迭代一个键的副本,即使用listtest和listtest[map]。@ekhumoro您说得对!我已经更新了我的答案。