【问题标题】:Python modifying dict entries in-place during iterationPython在迭代期间就地修改dict条目
【发布时间】:2019-02-19 16:39:08
【问题描述】:

我知道在一般情况下,在迭代 dict 时对其进行变异是不安全的:

d = {1: 2, 3: 4}
for k in d.keys():
    d[k + 1] = d[k] + 1

这会按预期产生RuntimeError。然而,在阅读documentation for dict 时,我发现了以下内容(强调我的):

在字典中添加或删除条目时迭代视图可能会引发RuntimeError 或无法迭代所有条目。

所以我尝试了以下代码:

d = {1: 2, 3: 4}
for k in d.keys():
    d[k] = d[k] + 1

注意:我在迭代过程中没有添加或删除任何条目;我只更新了现有条目。我已经尝试了几个示例,但到目前为止还没有收到RuntimeError,并且循环按预期工作。

这是否保证在该语言下有效?还是到目前为止我很幸运?

注意:我使用的是 Python 3,所以 d.keys() 返回动态视图而不是 list)。

【问题讨论】:

  • Alex Martelli 说 here 在给定的现有索引处分配不同的值不会产生任何问题,所以我认为应该没问题;)
  • 据我所知,这完全没问题(确实是你经常看到的东西)。关键是你实际上并没有改变d.keys() 的内容,当你添加或删除一个键时你就是这样 - 这几乎肯定是文档中的警告的内容。
  • 顺便说一句,d.keys() 对密钥进行迭代是多余的,只需使用 for k in d
  • @TomKarzes 这在 Python 中是不正确的。 Python不知道该值是否不可变,因此必须加载该值,然后无条件存储加法的结果。
  • @Dunes - 我不会将左侧称为“值”,但可以。它是否不可变并不重要。使用d[k] += 1,Python 只需评估一次d[k]。对于d[k] = d[k] + 1,Python 必须对d[k] 求值两次。

标签: python python-3.x dictionary language-lawyer


【解决方案1】:

字典的内部结构由键决定,而不是由值决定。至少目前。这意味着您可以修改与键关联的值,但添加或删除键(第一个示例的 d[k + 1] = d[k] + 1 所做的)会导致问题。

【讨论】: