为什么这里没有提出StopIteration?

时间:2014-10-24 16:35:01

标签: python iterator

看看这个,问题的关键在于底部:

>>> scan = iter('FHUR203459')
>>> while True:
        print(next(scan))


F
H
U
R
2
0
3
4
5
9
Traceback (most recent call last):
  File "<pyshell#11>", line 2, in <module>
    print(next(scan))
StopIteration
>>> scan = iter('FHUR203459')
>>> for i in range(12):  # 12 * 2 for each join is 24, much longer than the string; should raise error.
        print(''.join(next(scan) for i in range(2)))


FH
UR
20
34
59







>>>

换句话说,我们可以看到迭代器在两种情况下都达到了它的结束,但它只在第一种情况下引发了StopIteration,尽管在它到达之后两种情况都使用了next()。结束。为什么在join中使用它似乎可以逃避错误?或者这是一个错误吗?

2 个答案:

答案 0 :(得分:2)

str.join()在生成器上调用list(),该调用吞下StopIteration

使用迭代器的任何内容必须捕获StopIteration;究竟是什么引起了异常并不重要;生成器表达式或生成器表达式使用的任何内容:

>>> def raises_stopiteration(): raise StopIteration
... 
>>> next(raises_stopiteration() for _ in range(10))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <genexpr>
  File "<stdin>", line 1, in raises_stopiteration
StopIteration
>>> list(raises_stopiteration() for _ in range(10))
[]

答案 1 :(得分:2)

在第一种情况下,StopIteration不会在任何地方处理。但在第二种情况下,

''.join(next(scan) for i in range(2))

我们将生成器表达式传递给''.joinStopIteration处理由next(scan)引发的''.join,并且每次都会退出。这就是''.join产生空字符串的原因。

您可以稍微修改一下,然后将列表传递给>>> scan = iter('FHUR203459') >>> for i in range(12): ... print(''.join([next(scan) for i in range(2)])) ... FH UR 20 34 59 Traceback (most recent call last): File "<input>", line 2, in <module> File "<input>", line 2, in <listcomp> StopIteration 并查看自己引发的异常,就像这样

StopIteration

它显示{{1}}实际上已被提升,而列表理解则会获得此次点击。