首页 > 解决方案 > 文件对象迭代器是否“损坏”?

问题描述

根据文档

一旦迭代器的__next__()方法 raise StopIteration,它必须在后续调用中继续这样做。不遵守此属性的实现被视为已损坏。

但是,对于文件对象:

>>> f = open('test.txt')
>>> list(f)
['a\n', 'b\n', 'c\n', '\n']
>>> next(f)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> f.seek(0)
0
>>> next(f)
'a\n'

文件对象迭代器是否损坏?这只是那些无法修复的事情之一,因为它会破坏太多依赖它的现有代码吗?

标签: pythoniterator

解决方案


我认为这是,如果有的话,那段的文档错误,而不是io对象中的错误。(并且io对象并不是唯一的东西——最简单的是,文件的csv.reader包装器与文件一样可重新启动。)

如果您只是将迭代器用作迭代器,那么一旦它引发,它将继续引发。但是,如果你在迭代器协议之外调用方法,你就不再真正将它用作迭代器,而是将其用作比迭代器更多的东西。在这种情况下,如果有意义的话,将对象“重新填充”似乎是合法的,甚至是惯用的。只要它在作为迭代器嘎嘎作响时从不重新填充自己,只有在它作为其他类型的嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎的时候,它会超出这个范围。

在 C++ 中的类似情况下,语言委员会很可能会声明这会破坏可替代性,因此一旦您在其上调用此类方法,迭代器作为迭代器将变为无效,即使该语言无法强制执行。或者为可再填充的迭代器提出一个全新的协议。(当然 C++ 迭代器与 Python 迭代器并不完全相同,但希望你明白我的意思。)

但在 Python 中,实用性胜过纯粹性。我很确定 Guido 从一开始就打算这样做,并且允许对象这样做并且仍然被视为迭代器,核心开发人员继续打算这样做,只是没有人考虑过如何编写一些东西足够严谨来准确解释它,因为没有人问过。

如果您通过提交文档错误来询问,我敢打赌这一段会得到一个脚注,而不是io和其他可重新填充的迭代器对象被重新分类为实际上不是迭代器。


推荐阅读