Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何避免“RuntimeError:dictionary在迭代期间更改了大小”错误?_Python_List_Dictionary_Loops - Fatal编程技术网

Python 如何避免“RuntimeError:dictionary在迭代期间更改了大小”错误?

Python 如何避免“RuntimeError:dictionary在迭代期间更改了大小”错误?,python,list,dictionary,loops,Python,List,Dictionary,Loops,我已经检查了所有其他问题的相同错误,但没有找到有用的解决办法=/ 我有一本清单字典: d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]} 其中一些值为空。在创建这些列表的最后,我想在返回字典之前删除这些空列表。目前,我正尝试按如下方式执行此操作: for i in d: if not d[i]: d.pop(i) 但是,这给了我运行时错误。我知道,在遍历字典时,不能添加/删除字典中的元素……那么解决方法是什么呢?在Python 3

我已经检查了所有其他问题的相同错误,但没有找到有用的解决办法=/

我有一本清单字典:

d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}
其中一些值为空。在创建这些列表的最后,我想在返回字典之前删除这些空列表。目前,我正尝试按如下方式执行此操作:

for i in d:
    if not d[i]:
        d.pop(i)

但是,这给了我运行时错误。我知道,在遍历字典时,不能添加/删除字典中的元素……那么解决方法是什么呢?

在Python 3.x和2.x中,可以使用来强制创建密钥副本:

for i in list(d):
在Python 2.x中,调用创建了一个密钥副本,您可以在修改dict时对其进行迭代:


但是请注意,在Python3.x中,第二种方法对您的错误没有帮助,因为键返回a而不是将键复制到列表中。

只需使用字典理解将相关项复制到新的dict中即可

>>> d
{'a': [1], 'c': [], 'b': [1, 2], 'd': []}
>>> d = { k : v for k,v in d.iteritems() if v}
>>> d
{'a': [1], 'b': [1, 2]}
在Python3中实现了这一点

>>> d
{'a': [1], 'c': [], 'b': [1, 2], 'd': []}
>>> d = { k : v for k,v in d.items() if v}
>>> d
{'a': [1], 'b': [1, 2]}

首先,我会尽量避免插入空列表,但通常会使用:

d = {k: v for k,v in d.iteritems() if v} # re-bind to non-empty
如果在2.7之前:

d = dict( (k, v) for k,v in d.iteritems() if v )
或者只是:

empty_key_vals = list(k for k in k,v in d.iteritems() if v)
for k in empty_key_vals:
    del[k]
对于Python 3:

{k:v for k,v in d.items() if v}

您只需使用复制:

通过这种方式,您可以迭代原始字典字段,并动态更改所需的dict d dict。 这是每个python版本上的工作,因此更清晰

In [1]: d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}

In [2]: for i in d.copy():
   ...:     if not d[i]:
   ...:         d.pop(i)
   ...:         

In [3]: d
Out[3]: {'a': [1], 'b': [1, 2]}

运行时错误的原因是,当数据结构在迭代过程中发生更改时,您无法对其进行迭代

实现所需功能的一种方法是使用list附加要删除的键,然后在遍历列表时使用dictionary上的pop函数删除标识的键

d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}
pop_list = []

for i in d:
        if not d[i]:
                pop_list.append(i)

for x in pop_list:
        d.pop(x)
print (d)

对于这种情况,我喜欢制作一个深度副本,并在修改原始dict时循环该副本


如果查找字段在列表中,则可以在列表的for循环中枚举,然后将位置指定为索引,以访问原始目录中的字段。

在for循环过程中更改词典时,不能遍历词典。对列表进行转换并迭代该列表,这对我很有用

    for key in list(d):
        if not d[key]: 
            d.pop(key)

Python3不允许在使用字典上方的for循环进行迭代时删除。有多种选择可供选择;一个简单的方法是更改以下行

for i in x.keys():

这对我很有用:

dict = {1: 'a', 2: '', 3: 'b', 4: '', 5: '', 6: 'c'}
for key, value in list(dict.items()):
    if (value == ''):
        del dict[key]
print(dict)
# dict = {1: 'a', 3: 'b', 6: 'c'}  
将字典项强制转换为列表将创建其项的列表,因此您可以对其进行迭代并避免运行时错误。

dictc={stName:asas} keys=dictc.keys 对于输入列表键: dictc[key.upper]=“新值” 印刷品
避免在迭代错误期间更改字典大小 只需将“list”与“.items”一起使用,下面是一个简单的示例:

my_dict = {
    'k1':1,
    'k2':2,
    'k3':3,
    'k4':4
 
    }
    
print(my_dict)

for key, val in list(my_dict.items()):
    if val == 2 or val == 4:
        my_dict.pop(key)

print(my_dict)
+++ 输出:

{'k1':1,'k2':2,'k3':3,'k4':4}

{'k1':1,'k3':3}

+++

这只是一个示例,并根据您的案例/需求进行更改,
我希望这会有所帮助。

+1:最后一个选项很有趣,因为它只复制需要删除的项目的键。如果相对于dict的大小,只有少量项目需要删除,那么这可能会提供更好的性能。@MarkByers是的-如果有大量项目需要删除,那么将dict重新绑定到经过过滤的新项目是更好的选择。人们总是期望结构应该如何工作。重新绑定的危险在于,如果程序中的某个地方有一个对象引用了旧的dict,它将看不到更改。如果你确定不是这样的话,那么肯定。。。这是一个合理的方法,但重要的是要理解,这与修改原来的格言并不完全相同。@MarkByers非常好的观点——你和我都知道这一点,还有无数其他的,但这并不明显。我会把钱放在桌子上,它也不会在后面咬你:避免插入空条目是一个很好的方法。我相信你的意思是“调用键复制可以重复的键”,也就是复数键,对吗?否则,如何迭代单个键?顺便说一句,我不是吹毛求疵,我真的很想知道这是否是键或键或元组,而不是列表,因为它更快。为了澄清python 3.x的行为,d.keys返回一个iterable而不是迭代器,这意味着它是字典键的直接视图。一般来说,在Python3.x中使用for i in d.keys确实可以工作,但是因为它在字典键的可编辑视图上迭代,所以在循环期间调用d.pop会导致与您发现的相同的错误。因为listd中的i模拟了Python2在迭代之前将键复制到列表中的低效行为,对于像您这样的特殊情况,当您要删除内部目录中的对象时,python3解决方案不起作用。例如,您在目录a中有dic a和dict B。如果您要删除目录B中的对象,则在python3.x中会发生错误,listd.keys会创建与listd相同的输出,调用list on
dict返回键。钥匙打电话虽然不贵,但没有必要。d.iteritems给了我一个错误。我用d.items来代替——用python3解决OP的问题。然而,在多线程代码中碰到这个运行时错误后,任何人都会意识到,cPython的吉尔也可以在列表理解的中间被释放,而你必须以不同的方式来修复它。在Python 2.7中也为我工作过。从这里的所有答案来看,对于我来说,这是最简单和pythonic.quick和最简单的修复方法,在这个线程上列出的所有选项中,到目前为止。谢谢@singrium
dict = {1: 'a', 2: '', 3: 'b', 4: '', 5: '', 6: 'c'}
for key, value in list(dict.items()):
    if (value == ''):
        del dict[key]
print(dict)
# dict = {1: 'a', 3: 'b', 6: 'c'}  
my_dict = {
    'k1':1,
    'k2':2,
    'k3':3,
    'k4':4
 
    }
    
print(my_dict)

for key, val in list(my_dict.items()):
    if val == 2 or val == 4:
        my_dict.pop(key)

print(my_dict)