Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The yield from statement is a delegation mechanism in Python that allows a generator to yield all values from a sub-generator or iterable directly to the caller. Introduced in PEP 380, it establishes a transparent, bidirectional communication channel between the caller and the delegated sub-generator, automatically handling the propagation of values, exceptions, and return states.

Syntax

def delegating_generator():
    result = yield from iterable_or_subgenerator

Core Mechanics

When a generator executes a yield from statement, it suspends its own execution and delegates control to the specified iterable or sub-generator. The delegating generator remains suspended until the sub-generator is exhausted.

1. Value Propagation

For simple iterables, yield from acts as syntactic sugar for a standard iteration loop. Every value produced by the sub-generator is passed directly to the caller of the delegating generator.

# Naive equivalence for simple iterables
for item in iterable:
    yield item

2. Bidirectional Communication

Unlike a standard for loop, yield from binds the caller and the sub-generator together, allowing state to flow in both directions. If the caller uses generator methods to inject state, yield from routes them transparently:
  • send(value): Values sent to the delegating generator are passed directly into the sub-generator’s send() method. If the sub-generator is a simple iterable (which lacks a send method), send(None) is permitted, but sending any other value raises an AttributeError.
  • throw(type, value, traceback): Exceptions thrown into the delegating generator are routed to the sub-generator’s throw() method. If the delegated object is a simple iterable that lacks a throw() method, the thrown exception is simply raised directly in the delegating generator.
  • close(): Calling close() on the delegating generator automatically invokes the close() method on the sub-generator, ensuring proper resource cleanup. If the delegated object lacks a close() method, the call is ignored.

3. Return Value Extraction

In Python, generators can return a value upon completion, which is attached to the value attribute of the raised StopIteration exception. The yield from expression automatically catches this StopIteration, extracts the value, and evaluates to that value within the delegating generator.
def sub_generator():
    yield 1
    yield 2
    return "Execution finished"  # Attached to StopIteration.value

def delegating_generator():
    # 'yield from' yields 1 and 2 to the caller.
    # Once exhausted, it evaluates to "Execution finished".
    return_val = yield from sub_generator()
    yield f"Sub-generator returned: {return_val}"


# Execution:

# list(delegating_generator()) -> [1, 2, 'Sub-generator returned: Execution finished']

Exception Handling Behavior

The yield from statement enforces strict exception handling rules between the caller, the delegating generator, and the sub-generator:
  1. If the sub-generator raises a StopIteration, yield from consumes it and returns the exception’s value.
  2. If the sub-generator raises any other unhandled exception, the exception propagates up to the delegating generator, terminating the yield from expression.
  3. If a GeneratorExit exception is raised in the delegating generator (typically via close()), it is passed down to the sub-generator. If the sub-generator fails to exit (e.g., it catches GeneratorExit and yields another value), a RuntimeError is raised in the delegating generator.
Master Python with Deep Grasping Methodology!Learn More