Yield from Expression
yield from Expression
Introduced in Python 3.3 via PEP 380, the yield from <iterable> expression is often mistaken for a mere syntactic shortcut for a for item in iterable: yield item loop. In reality, yield from establishes a transparent, bidirectional communication channel between the caller and an inner subgenerator, seamlessly delegating values, exceptions, return values, and lifecycle events.
1. The Delegation Channel Architecture
When a delegating generator uses yield from, it creates a direct conduit connecting the outer caller with the inner subgenerator:
The delegating generator remains suspended while the subgenerator produces values. Data sent via send(), exceptions injected via throw(), and termination via close() bypass the delegating generator and pass directly into the subgenerator.
2. Capturing Return Values from Subgenerators
Prior to PEP 380, generators could not return values with meaningful data—any return value statement raised a SyntaxError or discarded the value.
With yield from, a subgenerator can return <value>. Python embeds this returned value inside the value attribute of the terminating StopIteration exception, and yield from automatically extracts it into a variable:
3. Bidirectional Communication Delegation
The power of yield from becomes apparent when sending values into a subgenerator via send():
4. Flattening Nested and Recursive Data Structures
yield from simplifies recursive tree traversal algorithms by eliminating manual nested iteration loops:
5. Architectural Comparison: for ... yield vs yield from
| Capability | for item in subgen: yield item | yield from subgen |
|---|---|---|
| Data Yielding | Supported | Supported |
send() Forwarding | Fails: Values sent to delegator are discarded or error | Supported: Transferred directly to subgenerator |
throw() Forwarding | Fails: Raises exception in delegator, not subgen | Supported: Injected cleanly into subgenerator |
close() Delegation | Requires complex manual try...finally boilerplate | Supported: Automatically cascades close() to subgen |
| Subgenerator Return Value | Lost: Cannot access return val easily | Captured: val = yield from subgen extracts return |
Multiple Choice Questions
1.
What is the primary difference between yield from subgenerator() and a standard for item in subgenerator(): yield item loop? A. yield from compiles the code to C for a $10\times$ speedup. B. yield from creates a bidirectional communication channel that forwards send(), throw(), and close(), while capturing subgenerator return values. C. yield from can only be used on string objects. D. A standard for loop does not work with generators.
yield from to establish a two-way pipeline between the caller and the subgenerator, delegating data, exceptions, termination signals, and return values transparently.2.
How does a delegating generator capture the value returned by a subgenerator via a return result statement? A. By reading subgen.__return__ B. By assigning the result of the yield from expression: result = yield from subgen() C. By catching a ReturnException D. Subgenerators are forbidden from returning values in Python.
return value, Python places the value in StopIteration.value. The yield from expression catches this automatically and evaluates to that returned value.3.
What occurs when delegator.send(data) is called while the delegating generator is suspended at yield from subgenerator()? A. The data is sent directly to subgenerator(). B. An AttributeError is raised. C. The delegating generator resumes and ignores the data. D. The subgenerator is immediately closed.
send() into the delegating generator are passed through directly to the active subgenerator at its current yield point.4.
What exception carries the return value of a completed generator under the hood? A. GeneratorExit B. StopIteration C. StopAsyncIteration D. Return
return expr statement, Python raises StopIteration(expr), storing expr in the value attribute of the exception instance.5.
Which PEP introduced the yield from syntax into Python? A. PEP 8 B. PEP 380 C. PEP 484 D. PEP 343
Coroutines with send()
Continue learning with hands-on practice, examples, and exercises in the upcoming topic.
Related Lessons
| Previous Lesson | Next Lesson |
|---|---|
| Advanced Generator Patterns | Coroutines with send() |
Practice Quiz
Test your understanding of this lesson with 5 questions. Each question has one correct answer.