Ответ 1
Когда foo()
возвращает обычный итеративный, эти два эквивалентны. "Магия" вступает в игру, когда foo()
также является генератором. В этот момент случаи yield from foo()
и for x in foo(): yield x
существенно отличаются.
Генератор также может быть отправлен с помощью метода generator.send()
. Когда вы используете цикл for
, выражение yield x
получает принятые данные; генератор foo()
никогда не увидит этого. Но когда вы используете yield from
, отправляемые данные поступают прямо к какому-либо выражению yield
, делегированный генератору в настоящее время приостановлен. Другими словами, yield from
передает отправленные данные, чтобы вместо этого делегированный генератор мог получить его.
Вы также можете создавать исключения в генераторе, generator.throw()
; с флагом цикла for
исключение возникает из строки yield x
, а при yield from
исключение снова передается; исключение создается внутри foo()
.
Вместе это означает, что yield from
по существу заменяет текущий генератор на время делегированной итерации.
Генерируемый делегированный генератор также получает возможность связываться с родительским генератором, когда завершенный атрибут .value
генерируемого исключения StopIteration
возвращается как значение выражения yield from
. Вы можете установить значение этого исключения, используя return <expression>
в генераторе делегированного-to foo()
, или вы можете явно использовать raise StopIteration(<expression>)
.
yield from
был введен на язык с PEP 380: синтаксис для делегирования в подгенератор.