在Python 3.6及以下版本中,这是默认行为,但被认为是语言错误,计划在Python 3.7中更改为引发异常。
如PEP 479所述:
生成器和StopIteration
的交互目前有些令人惊讶,并且可能掩盖晦涩的错误。不应该出现意外异常导致细微的行为变化,而应该引起响亮且易于调试的回溯。当前,在生成器函数内意外抛出的StopIteration
将被解释为驱动生成器的循环构造的迭代结束。
从Python 3.5开始,可以将默认行为更改为预定在3.7中的行为。这段代码:
from __future__ import generator_stop
def error():
return next(i for i in range(3) if i==10)
all(error() for i in range(2))
…引发以下异常:
Traceback (most recent call last):
File "gs_exc.py", line 8, in <genexpr>
all(error() for i in range(2))
File "gs_exc.py", line 6, in error
return next(i for i in range(3) if i==10)
StopIteration
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "gs_exc.py", line 8, in <module>
all(error() for i in range(2))
RuntimeError: generator raised StopIteration
在 Python 3.5 和 3.6 中,如果没有导入 __future__
,则会产生警告。例如:
def error():
return next(i for i in range(3) if i==10)
all(error() for i in range(2))
$ python3.5 -Wd gs_warn.py
gs_warn.py:6: PendingDeprecationWarning: generator '<genexpr>' raised StopIteration
all(error() for i in range(2))
$ python3.6 -Wd gs_warn.py
gs_warn.py:6: DeprecationWarning: generator '<genexpr>' raised StopIteration
all(error() for i in range(2))
any
函数返回的是可迭代对象中包含任何一个值为True
时即返回True
,而all
函数则在可迭代对象中不包含任何一个False
值时才返回True
。 - Adam Smithnext((i for i in range(3) if i==10), None)
将返回None
而不是抛出StopIteration
异常。 - Peter Wood