Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

Python yield from

Learn how Python's yield from delegates iteration to another iterable, how a delegated generator can return a value, and when delegation makes generator code clearer.

Levels: Intermediate ~22 min read

Intermediate

Python's yield from expression lets one generator delegate to another iterable. Instead of writing a loop just to pass each value along, the current generator can hand that job to the delegated iterable and continue when delegation ends.

Delegate values to another iterable

The expression yield from iterable yields the values produced by that iterable to the caller of the current generator.

python delegate.py
1
2
3
4
def countdown():
    yield from [3, 2, 1]

print(list(countdown()))

The outer generator yields the same values as the delegated list, in order.

The delegated object can be any iterable

The expression after yield from must be iterable. That can be a list, tuple, string, or another iterator or generator.

python iterable.py
1
2
3
4
def letters():
    yield from "ABC"

print(list(letters()))

A string is iterable, so delegation yields its characters one by one.

Continue after delegation finishes

When the delegated iterable is exhausted, the current generator continues with the next statement after yield from. This makes it easy to build one generator from several stages.

python stages.py
1
2
3
4
5
def report():
    yield from ["queued", "running"]
    yield "finished"

print(list(report()))

The generator delegates two values, then resumes its own body and yields the final value.

A subgenerator can return a value

When the delegated object is a generator that ends with return value, the yield from expression itself produces that value. The surrounding generator can capture it with ordinary assignment.

python return-value.py
1
2
3
4
5
6
7
8
9
def child():
    yield "step"
    return "done"

def parent():
    result = yield from child()
    print(f"child result: {result}")

print(list(parent()))

The caller receives the yielded value, while the parent generator receives the subgenerator's final return value.

Delegate through another generator

Delegation can form layers. Each generator can hand its work to another generator without manually repeating its loop.

python layers.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def source():
    yield from [10, 20, 30]

def middle():
    yield from source()

def outer():
    yield from middle()

print(list(outer()))

The values travel through each delegation layer to the caller.

Why use yield from?

Use yield from when one generator's job is to expose another iterable's sequence as part of its own sequence. It makes delegation explicit and leaves the current generator free to add more values before or after the delegated work.

python sections.py
1
2
3
4
5
6
7
def sections():
    yield "intro"
    yield from ["body-1", "body-2"]
    yield "summary"

for section in sections():
    print(section)

Delegation keeps the generator readable when a sequence already comes from another iterable.

yield from is not the same as yielding the iterable

A plain yield iterable yields the iterable object itself. yield from iterable instead delegates iteration so the iterable's values are produced one by one.

python compare.py
1
2
3
4
5
6
7
8
def whole():
    yield [1, 2, 3]

def parts():
    yield from [1, 2, 3]

print(list(whole()))
print(list(parts()))

One generator yields a single list value; the other delegates the list's individual values.

Keep the delegation boundary simple

Start with ordinary iteration and simple generator composition. Advanced generator communication and asynchronous delegation are separate topics; do not mix them into a first yield from lesson.

Was this page helpful?

Mark this learning resource complete to track your learning progress.