当我使用next()时为什么会出现StopIteration错误?

17
我无法澄清在Python(3)中使用next()的含义。
我有一个数据:
chr pos ms01e_PI    ms01e_PG_al ms02g_PI    ms02g_PG_al ms03g_PI    ms03g_PG_al ms04h_PI    ms04h_PG_al
2   15881989    4   C|C 6   A|C 7   C|C 7   C|C
2   15882091    4   A|T 6   A|T 7   T|A 7   A|A
2   15882148    4   T|T 6   T|T 7   T|T 7   T|G

我读到的是:

运行良好

c = csv.DictReader(io.StringIO(data), dialect=csv.excel_tab)
print(c)
print(list(c))

运行正常

c = csv.DictReader(io.StringIO(data), dialect=csv.excel_tab)
print(c)
keys = next(c)
print('keys:', keys)

但是,现在出现了一个问题。

c = csv.DictReader(io.StringIO(data), dialect=csv.excel_tab)
print(c)
print(list(c))
keys = next(c)
print('keys:', keys)

错误信息:

Traceback (most recent call last):
2   15882601    4   C|C 9   C|C 6   C|C 5   T|C

  File "/home/everestial007/Test03.py", line 24, in <module>
keys = next(c)
  File "/home/everestial007/anaconda3/lib/python3.5/csv.py", line 110, in __next__

    row = next(self.reader)

StopIteration

为什么在执行print(list(c))后再执行print(keys)会导致StopIteration错误?我已经阅读了文档,但对这个特定的例子不是很清楚。

1
当您调用list(c)时,您会消耗迭代器。迭代器现在为空,没有下一个项目。您可能想要了解一般的生成器知识。 - Patrick Haugh
1个回答

28
错误不在于print语句中,而是在于keys = next(c)这一行。考虑一个能够重现你问题的更简单的例子。
a = (i ** 2 for i in range(5))  

a           # `a` is a generator object
<generator object <genexpr> at 0x150e286c0>

list(a)     # calling `list` on `a` will exhaust the generator
[0, 1, 4, 9, 16]

next(a)     # calling `next` on an exhausted generator object raises `StopIteration`
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-2076-3f6e2eea332d> in <module>()
----> 1 next(a)

StopIteration: 

发生的情况是,c 是一个迭代器对象(与上面的 生成器 a 非常相似),它的目的是被迭代一次直到用尽。对此对象调用 list 会用尽它,以便将元素收集到列表中。

一旦对象被用尽,它将不会再产生任何元素。在这一点上,生成器机制被设计为在你尝试迭代它甚至在它被用尽后仍然迭代时引发 StopIteration。诸如 for 循环的结构会侦听此错误并默默地吞咽它,但是 next 在引发异常后立即返回原始异常。


2
这种错误也可能在生成器自执行以来一直为空的情况下引发。例如,使用os.walk作为生成器从目录返回路径,如果目录不存在,则os.walk将为空,因此next()将引发StopIteration错误。 - Luan Souza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接