在遍历Python字典时修改它

139 投票
9 回答
123255 浏览
提问于 2025-04-16 22:00

假设我们有一个Python字典 d,我们正在像这样遍历它:

for k, v in d.iteritems():
    del d[f(k)] # remove some item
    d[g(k)] = v # add a new item

fg 只是一些不透明的转换过程。)

换句话说,我们在使用 iteritems 遍历的时候,试图向 d 中添加或删除一些项目。

这样做是否合理?你能提供一些参考资料来支持你的回答吗?


另外,查看 如何避免“RuntimeError: dictionary changed size during iteration”错误? 这个问题,了解如何避免这个问题。

9 个回答

37

你不能这样做,至少用 d.iteritems() 是不行的。我试过了,Python 会报错:

RuntimeError: dictionary changed size during iteration

如果你用 d.items(),那就可以正常工作了。

在 Python 3 中,d.items() 是字典的一个视图,类似于 Python 2 中的 d.iteritems()。在 Python 3 中,要实现这个功能,可以用 d.copy().items()。这样做可以让我们遍历字典的一个副本,从而避免在遍历时修改原来的数据结构。

96

Alex Martelli在这里对这个问题发表了看法,具体可以查看这个链接

在遍历一个容器(比如字典)的时候,直接修改这个容器可能会不安全。所以像del d[f(k)]这样的操作可能会出问题。你可以用一个变通的方法,就是用d.copy().items()来遍历容器的一个独立副本,而不是用d.iteritems()d.items()(这两个是直接操作同一个容器)。

在字典中,修改一个已经存在的索引的值是没问题的,但如果你想在新的索引位置插入值(比如d[g(k)] = v),可能就会出现问题。

67

在Python的文档页面上(针对Python 2.7),明确提到:

在字典中使用iteritems()时,如果你正在添加或删除条目,可能会引发RuntimeError错误,或者无法遍历所有条目。

对于Python 3也是如此。

同样的情况也适用于iter(d)d.iterkeys()d.itervalues(),我甚至可以说for k, v in d.items():也有可能会遇到这个问题(我不太记得for具体是怎么做的,但如果它调用了iter(d),我也不会感到惊讶)。

撰写回答