Skip to main content
🔗
PEP 380 · Speedrun · Python 3.3 (2012)

PEP 380 in 90 seconds — yield from and the bones of async/await

Delegate a whole generator in one line — and skip the boilerplate forever.

Before `yield from`, delegating to a sub-generator was 4 lines of forwarding boilerplate: ```python def wrap(gen): for x in gen: yield x # one level of nesting — already tedious ``` For two levels (a generator yielding from another generator yielding from a third) it got worse — you couldn't easily forward `.send()`, `.throw()`, or the sub-generator's return value. PEP 380 (Python 3.3, 2012) collapsed it into one keyword.

`yield from sub_gen` does **all** of: - Yields every value `sub_gen` produces - Forwards `.send()` / `.throw()` from the outer caller to `sub_gen` - Captures `sub_gen`'s return value (Python 3.3+ generators can `return X` to end with a value) It's the layer `asyncio` was built on top of. `await x` in an `async def` is effectively `yield from x` underneath — just with the asyncio event loop driving the iteration.

Before — manual for-yield loop
def numbers():
    yield 1
    yield 2
    yield 3

def wrap_old():
    for x in numbers():    # boilerplate
        yield x
    yield 4

print(list(wrap_old()))  # [1, 2, 3, 4]
After — yield from (Python 3.3+)
def numbers():
    yield 1
    yield 2
    yield 3

def wrap_new():
    yield from numbers()   # delegates everything
    yield 4

print(list(wrap_new()))  # [1, 2, 3, 4]

# Also: forwards .send() / .throw() / captures return value:
def producer():
    val = yield "hello"
    return f"got: {val}"

def wrapper():
    result = yield from producer()
    yield result

🎯 Predict the output

What does this print? `yield from` inlines every value of the sub-generator, in order.

def squares():
    for i in range(3):
        yield i ** 2

def combined():
    yield "start"
    yield from squares()
    yield "end"

print(list(combined()))
Generators & iteration → Foundations track

Or speedrun another PEP

PEP 572Assignment as an expression — 3 lines become 1.
PEP 572 in 90 seconds — the walrus that ate your for-loop
PEP 484Python stays dynamic — but you can opt into typing.
PEP 484 in 90 seconds — type hints, without TypeScript-envy
PEP 622Switch statements are a 5% feature. Pattern matching is the 95%.
PEP 622 in 90 seconds — match / case isn't just a switch