Обложка канала

Библиотека Python разработчика

20835 @BookPython

Библиотека Python разработчика. Книги по программированию на Python.

Библиотека Python разработчика

4 года назад
Открыть в
Every call to next(x) returns the new value from the x iterator unless an exception is raised. If this is StopIteration, it means the iterator is exhausted and can supply no more values. If a generator is iterated, it automatically raises StopIteration upon the end of the body: >>> def one_two(): ... yield 1 ... yield 2 ... >>> i = one_two() >>> next(i) 1 >>> next(i) 2 >>> next(i) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration StopIteration is automatically handled by tools that calls next for you: >>> list(one_two()) [1, 2] The problem is, any unexpected StopIteration that is raised within a generator causes it to stop silently instead of actually raising an exception: def one_two(): yield 1 yield 2 def one_two_repeat(n): for _ in range(n): i = one_two() yield next(i) yield next(i) yield next(i) print(list(one_two_repeat(3))) The last yield here is a mistake: StopIteration is raised and makes list(...) to stop the iteration. The result is [1, 2], surprisingly. However, that was changed in Python 3.7. Such foreign StopIteration is now replaced with RuntimeError: Traceback (most recent call last): File "test.py", line 10, in one_two_repeat yield next(i) StopIteration The above exception was the direct cause of the following exception: Traceback (most recent call last): File "test.py", line 12, in <module> print(list(one_two_repeat(3))) RuntimeError: generator raised StopIteration You can enable the same behavior since python3.5 by from __future__ import generator_stop.