【问题标题】:what are the rules for iterator invalidation?迭代器失效的规则是什么?
【发布时间】:2016-10-26 11:11:55
【问题描述】:

是否有所有模块都遵循的一般规则?

In my case,我正在使用Python xml.etree library

假设我这样做:

for el in root.iter('*'):
    for subel in el:
        el.remove(subel)

这会破坏el 迭代器吗?

【问题讨论】:

  • 不......任何人都可以实现自己的迭代器,它可以真正做任何事情......只要它返回的是可迭代的
  • 经验法则是“不要修改任何你正在迭代的东西”。很少有人提供明确的 C++ 风格的迭代器失效规则。
  • @mgilson 是的,哎呀。
  • @user2357112 如何测试任何给定 Python 模块的具体实现是什么?我不确定我是否可以,因为只有有效的测试是“是否失败”,因为如果在这个实例中没有失败并不意味着它在其他实例中不会失败。
  • 是的,一般来说stackoverflow.com/questions/37702011/…很糟糕

标签: python xml iterator


【解决方案1】:

在很多情况下,在迭代迭代时修改可迭代对象会导致问题。 Here's 一个示例,当在迭代过程中删除一个元素时,XML 树的迭代会变得混乱。 stackoverflow 上有很多问题,在迭代列表时会得到令人惊讶的结果:

>>> lst = [1, 1, 2, 3]
>>> for item in lst:
...     if item == 1:
...         lst.remove(item)
... 
>>> print(lst)
[1, 2, 3]

(注意输出列表中还有一个1)。

所以 一般 规则是,您可能不应该在迭代器执行此操作时执行任何会添加或删除项目的操作。 如果您不知道迭代器是如何实现的,这是迄今为止最安全的方法。但是,一些迭代器被记录为以特定方式工作。例如以上面的列表为例,如果我们反向迭代列表,我们可以删除当前(或较低索引的元素):

>>> lst = [1, 1, 2, 3]
>>> for item in reversed(lst):
...     if item == 1:
...         lst.remove(item)
... 
>>> print(lst)
[2, 3]

这是由于列表迭代器做出的某些保证。请注意,由于我上面列出的一般规则,我不建议这样做(这可能会导致您的代码阅读者挠头试图弄清楚您为什么要向后迭代它)。

对于列表案例,如果他们计划删除/添加元素,您会看到人们迭代列表的副本,但是如果不了解更多关于列表的约束,就很难为一般迭代器案例提供建议问题。

【讨论】:

    猜你喜欢
    • 2013-05-30
    • 2011-09-20
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 2023-01-13
    相关资源
    最近更新 更多