在遍历Python字典时修改它
假设我们有一个Python字典 d
,我们正在像这样遍历它:
for k, v in d.iteritems():
del d[f(k)] # remove some item
d[g(k)] = v # add a new item
(f
和 g
只是一些不透明的转换过程。)
换句话说,我们在使用 iteritems
遍历的时候,试图向 d
中添加或删除一些项目。
这样做是否合理?你能提供一些参考资料来支持你的回答吗?
另外,查看 如何避免“RuntimeError: dictionary changed size during iteration”错误? 这个问题,了解如何避免这个问题。
9 个回答
你不能这样做,至少用 d.iteritems()
是不行的。我试过了,Python 会报错:
RuntimeError: dictionary changed size during iteration
如果你用 d.items()
,那就可以正常工作了。
在 Python 3 中,d.items()
是字典的一个视图,类似于 Python 2 中的 d.iteritems()
。在 Python 3 中,要实现这个功能,可以用 d.copy().items()
。这样做可以让我们遍历字典的一个副本,从而避免在遍历时修改原来的数据结构。
Alex Martelli在这里对这个问题发表了看法,具体可以查看这个链接。
在遍历一个容器(比如字典)的时候,直接修改这个容器可能会不安全。所以像del d[f(k)]
这样的操作可能会出问题。你可以用一个变通的方法,就是用d.copy().items()
来遍历容器的一个独立副本,而不是用d.iteritems()
或d.items()
(这两个是直接操作同一个容器)。
在字典中,修改一个已经存在的索引的值是没问题的,但如果你想在新的索引位置插入值(比如d[g(k)] = v
),可能就会出现问题。
在Python的文档页面上(针对Python 2.7),明确提到:
在字典中使用
iteritems()
时,如果你正在添加或删除条目,可能会引发RuntimeError
错误,或者无法遍历所有条目。
对于Python 3也是如此。
同样的情况也适用于iter(d)
、d.iterkeys()
和d.itervalues()
,我甚至可以说for k, v in d.items():
也有可能会遇到这个问题(我不太记得for
具体是怎么做的,但如果它调用了iter(d)
,我也不会感到惊讶)。