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

Abh*_*jit 3 python dictionary iterator runtime-error

在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
>>>
Run Code Online (Sandbox Code Playgroud)

由于一些奇怪的原因,我第一次迭代字典,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)
Run Code Online (Sandbox Code Playgroud)

Sve*_*ach 11

在迭代时添加或删除字典的项是错误的.既然somehash是a defaultdict,甚至看起来像是行中的只读访问

if somehash[maxkey] > k:
Run Code Online (Sandbox Code Playgroud)

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


Fas*_*tle 6

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

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

for k, v in somehash.items():
    if somehash[maxkey] > v:
        maxkey = k
Run Code Online (Sandbox Code Playgroud)

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

  • 对我来说不起作用,必须显式地具体化这些项目(通过“list(the_dict.items())”工作)才能停止错误。`.items()` 返回字典的视图,每个 https://docs.python.org/3/library/stdtypes.html#dict-views 反映了底层字典中的更改,因此可能会导致相同的问题 (3认同)