底层对象更改时的Python迭代器

时间:2014-04-10 11:56:44

标签: python iterator

如果底层对象在迭代期间发生变化,我想知道迭代器的一般行为是什么。

使用一个简单的可变列表,似乎很明显:迭代器将尝试跟随下一个元素(如果有的话),如果到达结束则发送StopIteration

>>> l = range(10)
>>> a = iter(l)
>>> a.next()
0
>>> a.next()
1
>>> a.next()
2
>>> l[3]='a'
>>> a.next()
'a'
>>> a.next()
4
>>> del l[5]
>>> a.next()
6
>>> a.next()
7
>>> a.next()
8
>>> a.next()
9
>>> a.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

到目前为止,这是不言自明的。我不明白的是,如果我追加一个新元素,迭代器仍会返回StopIteration

>>> l.append(11)
>>> a.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

如果我在结束前也这样做:

>>> l=[1]
>>> a=iter(l)
>>> a.next()
1
>>> l.append(2)
>>> a.next()
2

这是如何工作的?更复杂的可变迭代对象的预期行为是什么? (例如,想象一个表示图形的对象,然后可以使用遍历算法迭代它。如果在迭代时添加/删除节点,应该发生什么?)

3 个答案:

答案 0 :(得分:2)

PEP 234(迭代器)中对该特定问题发表了评论:

  

一旦特定的迭代器对象引发了StopIteration,就会   它还会在所有后续的next()调用中引发StopIteration?

     

有些人说,要求这样做是有用的,其他人说   将它打开给各个迭代器是有用的。   请注意,这可能需要额外的状态位   迭代器实现(例如函数包装迭代器)。

     

解决方案:一旦引发StopIteration,调用it.next()   继续提高StopIteration

     

注意:事实上这在Python 2.2中没有实现;有   迭代器的next()方法可以引发的很多情况   StopIteration在一个电话上但不在下一个电话上。这一直是   在Python 2.3中补救。

答案 1 :(得分:0)

在迭代对象时有三种典型的更改对象的行为:

  • 将返回新数据
  • 新数据将被忽略
  • 旧数据将被跳过

换句话说:实际行为未定义。

在迭代它们时更改对象是一个常见的问题,在Python 3中,类型setdict(以及可能的其他类型)被更改为在检测到添加或删除期间立即引发错误迭代。

答案 2 :(得分:0)

有些迭代器即使在e被引发后也可以产生更多数据;这样的迭代器是considered broken

这并不意味着迭代器出错 - 这意味着如果你不小心使用这样的迭代器,你最终可能会遇到错误和破坏的代码。