【问题标题】:RuntimeError: dictionary changed size during iteration - During Iteration with iteritems on a defaultdictRuntimeError:字典在迭代期间更改了大小 - 在迭代期间使用 defaultdict 上的 ititems
【发布时间】:2012-01-06 18:46:06
【问题描述】:

在 SO 中回答特定问题时,我偶然发现了一个我无法解释的特殊问题。不幸的是,前两个 Google 搜索页面返回了一个 SO 页面,这也没有帮助。

问题代码

>>> somedata=[random.randint(1,1000) for i in xrange(1,10000)]
>>> somehash=collections.defaultdict(int)
>>> for d in somedata:
    somehash[d]+=1      
>>> maxkey=0
>>> for k,v in somehash.iteritems():
    if somehash[maxkey] > v:
        maxkey=k            

Traceback (most recent call last):
  File "<pyshell#700>", line 1, in <module>
    for k,v in somehash.iteritems():
RuntimeError: dictionary changed size during iteration
>>> for k,v in somehash.iteritems():
    if somehash[maxkey] > v:
        maxkey=k
>>>

由于一些奇怪的原因,我第一次迭代字典时,Python 正在发脾气,但随后的执行很好,正如您在示例中看到的那样,我第一次迭代字典时,它给出了运行时错误,但下一次它没有抱怨。

知道可能出了什么问题吗?

以防万一

>>> sys.version_info
sys.version_info(major=2, minor=7, micro=0, releaselevel='final', serial=0)
>>> sys.version
'2.7 (r27:82525, Jul  4 2010, 09:01:59) [MSC v.1500 32 bit (Intel)]'

OS: Microsoft Windows [Version 6.1.7601] (Windows 7)

【问题讨论】:

  • 比较somehash[maxkey] &gt; k将dict中的计数与哈希值进行比较,这似乎毫无意义。你想做什么?
  • @Sven,这是一个拼写错误。我会纠正它。它应该是somehash[maxkey] &gt; v,我正在尝试迭代并确定字典中的最大值,同时只跟踪键。

标签: python dictionary iterator runtime-error


【解决方案1】:

在迭代字典时添加或删除项目是错误的。由于somehashdefaultdict,因此即使是行中的只读访问权限

if somehash[maxkey] > k:

可能会添加一个新密钥——导致您遇到的错误。

【讨论】:

  • 具体来说,在maxkey=0 的第一次迭代中会引发错误。您的其他键来自字典,因此它们已经存在。
  • 这就是问题所在,使用普通的 dict 会引发一个关键错误,但这仍然没有引起注意。
【解决方案2】:

正如 Sven 所解释的,您遇到的错误是由于 defaultdict 的工作方式造成的。在defaultdict 中执行查找时,如果键不存在,则检索默认值(因此名称)并将键添加到字典中(使用默认值)。这是您的RuntimeError 的来源。

您可以执行以下操作来避免此问题:

for k, v in somehash.items():
    if somehash[maxkey] > v:
        maxkey = k

主要区别在于 somehash.items() 返回一个 (key, value) 元组列表,因此您实际上是在迭代该列表而不是 somehash 本身。 .keys().iterkeys() 也是如此。

【讨论】:

  • 对我不起作用,必须明确具体化这些项目(通过 list(the_dict.items()) 工作)以停止错误。 .items() 返回字典的视图,每个 docs.python.org/3/library/stdtypes.html#dict-views 反映底层字典的变化,因此可能导致相同的问题
【解决方案3】:

您正在生成 9999(有点)随机整数介于 1 和 1000 中,存储在 somedata 中,用作 somehash 的键,用于存储数字在 somedata 中的出现.

作为maxkey=0,该密钥永远不会存在。由于您使用的是默认字典,when each key is encountered for the first time, an entry is automatically created using the default_factory function which returns an empty list,因此在迭代期间正确地抛出了错误,* FastTurtle* 已经指出。

使用get 方法安全地检索项目。

import random
import collections

somedata=[random.randint(1,1000) for i in xrange(1,10000)]
somehash=collections.defaultdict(int)
for d in somedata:
   somehash[d]+=1 

maxkey=0
for k,v in somehash.iteritems():
   if somehash.get(maxkey) > v:
       maxkey=k 
       print k,v  

我看到您正在使用 Python 2.7,它有一个名为 Counter 的新集合类,用于计算可散列对象。使用Counter 应该比上面的代码更快,并且将你的代码减少到:

somedata=[random.randint(1,1000) for i in xrange(1,10000)]
somehash=collections.Counter(somedata)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-25
    • 2012-11-15
    相关资源
    最近更新 更多