繁体   English   中英

RuntimeError:迭代期间字典改变了大小 - 在defaultdict上使用iteritems进行迭代

[英]RuntimeError: dictionary changed size during iteration - During Iteration with iteritems on a defaultdict

在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)

在迭代时添加或删除字典的项是错误的。 由于somehashdefaultdict ,甚至什么似乎像在线路只读访问

if somehash[maxkey] > k:

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

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

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

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

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

您正在生成9999(有些) 1到1000之间的随机整数,存储在somedata ,用作somehash的键,用于存储somedata中数字的出现。

maxkey=0 ,该密钥将永远不存在。 在使用defaultdict时, 当第一次遇到每个键时,会使用default_factory函数自动创建一个条目,该函数返回一个空列表 ,因此在迭代期间正确地抛出错误,方式是* 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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM