Почему вложенные операторы yield from (делегирование генератора) приводят к завершающему значению `None`?
Возможно ли гнездиться yield from
заявления?
Простая форма очевидна:
def try_yield1():
x = range(3)
yield from x
Который производит:
0
1
2
Но что, если у меня есть вложенные генераторы?
def try_yield_nested():
x = [range(3) for _ in range(4)]
yield from ((yield from y) for y in x)
Это производит:
0
1
2
None # why?
0
1
2
None # ...
0
1
2
None # ...
Почему это производит None
если бы я использовал yield from
(хотя он вложенный)?
Я знаю, что могу сделать что-то вроде:
from itertools import chain
def try_yield_nested_alternative():
x = [range(3) for _ in range(4)]
yield from chain.from_iterable(x)
Который производит тот же результат, оставляя вне None
(это то, что я ожидаю). Я также могу написать простой цикл:
for x in [range(3) for _ in range(3)]:
yield from x
Но я подумал, что было бы более питонно использовать вложенное делегирование (желательно даже yield from x from y
или же yield from x for x in y
, но это не правильный синтаксис). Почему это не работает, как я ожидаю?
1 ответ
yield
это выражение, оно будет оценивать все, что вы send(value)
Это. Проще говоря, если вы ничего не отправите, вы получите None
выход, потому что значение yield
было бы None
,
yield from
сам по себе равен None
и вы используете два из них. На втором yield from
вы перебираете список, который вводит генератор с элементами этого списка, но вы также используете yield from
вернуть это выражение генератора, которое возвращает список, а также сам, который эквивалентен None
на каждой итерации, таким образом, почему после каждой итерации элемента диапазона вы получаете None
,
По сути это то, что происходит:
(yield from y) for y in x
дает значения, [0, 1, 2]yield from
дает значения из предыдущего, а такжеyield from
от предыдущего, который являетсяNone
,- Оценивая [0, 1, 2], а затем добавляя
None
из-заyield from
в(yield from y) for y in x
,
К сожалению, нет способа избавиться от None
вывод, в связи с характером выражения. Вам лучше использовать from_iterable
,
Источник, объясняющий выражение доходности; https://docs.python.org/2.5/ref/yieldexpr.html