如果底层对象在迭代期间发生变化,我想知道迭代器的一般行为是什么。
使用一个简单的可变列表,似乎很明显:迭代器将尝试跟随下一个元素(如果有的话),如果到达结束则发送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
这是如何工作的?更复杂的可变迭代对象的预期行为是什么? (例如,想象一个表示图形的对象,然后可以使用遍历算法迭代它。如果在迭代时添加/删除节点,应该发生什么?)
答案 0 :(得分:2)
在PEP 234(迭代器)中对该特定问题发表了评论:
一旦特定的迭代器对象引发了StopIteration,就会 它还会在所有后续的next()调用中引发StopIteration?
有些人说,要求这样做是有用的,其他人说 将它打开给各个迭代器是有用的。 请注意,这可能需要额外的状态位 迭代器实现(例如函数包装迭代器)。
解决方案:一旦引发StopIteration,调用it.next() 继续提高StopIteration 。
注意:事实上这在Python 2.2中没有实现;有 迭代器的next()方法可以引发的很多情况 StopIteration在一个电话上但不在下一个电话上。这一直是 在Python 2.3中补救。
答案 1 :(得分:0)
在迭代对象时有三种典型的更改对象的行为:
换句话说:实际行为未定义。
在迭代它们时更改对象是一个常见的问题,在Python 3中,类型set
和dict
(以及可能的其他类型)被更改为在检测到添加或删除期间立即引发错误迭代。
答案 2 :(得分:0)
有些迭代器即使在e
被引发后也可以产生更多数据;这样的迭代器是considered broken
。
这并不意味着迭代器出错 - 这意味着如果你不小心使用这样的迭代器,你最终可能会遇到错误和破坏的代码。