Ответ 1
Хотя это поведение по умолчанию в версиях Python до 3.6 включительно, оно считается ошибкой в языке и должно изменяться в Python 3.7, так что вместо этого возникает исключение.
Как PEP 479 говорит:
Взаимодействие генераторов и
StopIteration
в настоящее время несколько удивительно и может скрывать неясные ошибки. Неожиданное исключение не должно приводить к тонко измененному поведению, но должно вызывать шумную и легко отлаженную трассировку. В настоящее времяStopIteration
, случайно вызванный внутри функции генератора, будет интерпретироваться как конец итерации контуром, управляющим генератором.
Начиная с версии Python 3.5, можно изменить поведение по умолчанию на 3,7. Этот код:
# gs_exc.py
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__
возникает предупреждение. Например:
# gs_warn.py
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))