a
- объект генератора.Когда вы в первый раз вызываете next
, тело вычисляется с точностью до первого выражения yield
(то есть первого, которое будет оценено: внутреннего).Это yield
производит значение 1
для возврата next
, затем блокируется до следующего входа в генератор.Это вызвано вторым вызовом next
, который не отправляет любое значение в генератор.В результате первый (внутренний) yield
оценивается как None
.Это значение используется в качестве аргумента для внешнего yield
, которое становится возвращаемым значением второго вызова next
.Если вы вызовете next
в третий раз, вы получите исключение StopIteration
.
Сравните использование метода send
(вместо next
) для изменения возвращаемого значенияпервое yield
выражение.
>>> a = mygen()
>>> next(a)
1
>>> a.send(3) # instead of next(a)
3
>>> next(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Более явный способ написания генератора был бы
def mygen():
x = yield 1
yield x
a = mygen()
print(a.send(None)) # outputs 1, from yield 1
print(a.send(5)) # makes yield 1 == 5, then gets 5 back from yield x
print(a.send(3)) # Raises StopIteration, as there's nothing after yield x
До Python 2.5, yield
оператор обеспечивает одностороннюю связь между вызывающим абонентом и генератором;вызов next
выполнит генератор до следующего оператора yield
, а значение, предоставленное ключевым словом yield
, будет служить возвращаемым значением next
.Генератор также приостанавливается в точке оператора yield
, ожидая возобновления следующего вызова next
.
В Python 2.5 оператор yield
был заменен * на yield
выражение , и генераторы получили метод send
.send
работает очень похоже на next
, за исключением того, что может принимать аргумент.(В остальном, предположим, что next(a)
эквивалентно a.send(None)
.) Генератор начинает выполнение после вызова send(None)
, после чего он выполняет до первого yield
, который возвращает значение какдо.Однако теперь выражение блокируется до следующего следующего вызова send
, после чего выражение yield
соответствует аргументу, переданному send
.Генератор теперь может получать значение при возобновлении.
* Не полностью заменено;В ответе Кодзиро более подробно говорится о тонкой разнице между выражением yield
и выражением yield
.