Python yield Keyword

Learn what yield means in Python and how it creates generator functions. Understand yield vs return, next(), for loops, generator expressions, yield from, and common mistakes with simple examples.

Published

Updated

Read time 6 min read

Reviewed byDeepak Prasad

Python yield Keyword

yield marks a generator function. Calling that function does not run the whole body at once—it returns a generator object that produces values one step at a time. Each yield pauses the function, sends out a value, and saves local variables until the next step.

This page explains what yield means, a minimal example, how it differs from return, driving generators with next() and for, when generators help, and yield from. Generators are a specialized form of Python function—start with plain def and return before leaning on lazy iteration. Advanced topics such as send(), async generators, and threading are out of scope here; see the official generator tutorial when you need those.

Tested on: Python 3.13.3; kernel 6.14.0-37-generic.


What does yield mean in Python?

In a normal function, return ends execution and hands back a result. With yield, the function becomes a generator:

  1. The first call returns a generator object (the body has not run yet, beyond creating that object).
  2. Each next() call (or each step of a for loop) runs the function until the next yield.
  3. The function pauses at yield, delivers a value, and keeps its local state.
  4. When the function falls off the end or hits return, iteration stops with StopIteration.
python
def count_up_to(max):
    count = 1
    while count <= max:
        yield count
        count += 1

counter = count_up_to(3)
print(type(counter))
print(next(counter))
print(next(counter))
Output

You should see <class 'generator'>, then 1, then 2. A third next(counter) would print 3; one more raises StopIteration.

A generator is lazy: values are computed when requested, not all upfront in a list. That matters for long sequences or pipelines, but the core idea to remember first is pause, produce, resume—not performance tuning.


Python yield example

A generator with several yield statements produces values in order:

python
def greet_people():
    yield "Hello, John"
    yield "Hello, Jane"
    yield "Hello, Jim"

for greeting in greet_people():
    print(greeting)
Output

You should see three greeting lines. The function runs in chunks: it starts, hits the first yield, stops; the loop asks for the next value; execution picks up after that yield, and so on.

Another common shape is yield inside a loop when you do not want to build a full list in memory:

python
def first_n_squares(n):
    for x in range(n):
        yield x * x

print(list(first_n_squares(5)))
Output

You should see [0, 1, 4, 9, 16]. Here we materialize with list() for display; in real code you often keep the generator and iterate once.


yield vs return in Python

return yield
Function type Normal function Generator function
On call Runs to completion (or first return) Returns a generator object
Result One value (or a tuple / list you return) Many values over time
State Lost after the function exits Preserved between steps
Typical use Compute and give back a final answer Stream or sequence of values
python
def make_list():
    return [1, 2, 3]

def make_gen():
    yield 1
    yield 2
    yield 3

print(make_list())
print(type(make_gen()))
print(list(make_gen()))
Output

You should see [1, 2, 3], then <class 'generator'>, then [1, 2, 3] again from the generator.

return inside a generator still ends iteration (optionally with a value attached to StopIteration in Python 3.3+). You cannot mix “return a list of everything” and “yield items one by one” in the same function for the same purpose—pick one model per function.

State preservation is the behavioral difference people notice first:

python
def count_to_two():
    print("before first yield")
    yield 1
    print("before second yield")
    yield 2

g = count_to_two()
print(next(g))
print(next(g))
Output

You should see before first yield, 1, before second yield, 2. Code after a yield runs only on later steps—not on the initial call that created g.


How generators work with next() and for loop

next(gen) advances the generator by one step. When there is nothing left, Python raises StopIteration:

python
def three_values():
    yield "a"
    yield "b"
    yield "c"

g = three_values()
print(next(g))
print(next(g))
print(next(g))
try:
    next(g)
except StopIteration:
    print("done")
Output

You should see a, b, c, then done.

A for loop does the same thing under the hood: it calls next() repeatedly until StopIteration. That is why you write the loop shown below instead of managing next() yourself. For loop syntax and for / else, see Python for loop.

python
for value in three_values():
    print(value)
Output

Every generator is an iterator: you get one pass. After exhaustion, a second loop over the same object produces nothing:

python
g = (x for x in range(3))
print(list(g))
print(list(g))
Output

You should see [0, 1, 2] then []. Generators do not support len() without consuming them—another sign they are streams, not stored sequences.


When to use yield in Python

Use a generator when you want to produce a sequence lazily—one item at a time—without building a large list first.

Good fits:

  • Stepping through a long or unbounded sequence (range-like logic, Fibonacci, paginated chunks).
  • Piping data through stages (read → filter → transform) where each stage yields rows.
  • A one-off iterable from a generator expression (x * x for x in range(n)) instead of a list comprehension when you only iterate once.
python
print(sum(x * x for x in range(5)))
Output

You should see 30. Parentheses make a generator expression; square brackets would build a list first.

Reach for a normal function with return when you need random access, repeated traversals, or a concrete collection to index and slice. If you call a generator function expecting a list, you only get a generator object—wrap with list(...) when you truly need all values in memory.

Common mistakes:

  • Calling make_gen() and treating the result like a list without iterating.
  • Expecting a second for loop over the same generator to replay values.
  • Using yield in a short function where return [ ... ] is clearer and small enough to fit in memory.

For writing many lines to disk, generators often pair with file loops; see Python write to file for the file side. This page stays focused on yield itself.


Python yield from

yield from delegates to another generator or iterable. Python pulls every value from the sub-iterator for you—handy for recursive flattening:

python
def flatten(nested):
    for item in nested:
        if isinstance(item, list):
            yield from flatten(item)
        else:
            yield item

print(list(flatten([1, [2, [3, 4], 5]])))
Output

You should see [1, 2, 3, 4, 5]. Without yield from, the inner call would need an explicit loop:

python
for sub in flatten(item):
    yield sub
Output

yield from also forwards send() and throw() in advanced code; for most scripts, read it as “yield everything from this other generator.” Details are in PEP 380.


Summary

yield turns a function into a generator that pauses at each yield, produces one value, and resumes later with local state intact. Calling the function returns a generator object; next() and for drive it until StopIteration. Use return when you need a single finished result; use yield when you want a lazy sequence. Generators run once—replay requires a new generator or a list. yield from delegates to another iterable, which simplifies nested patterns like flattening. For deeper material (send, async generators), use the Python docs on generators.


Frequently Asked Questions

1. What does yield do in a Python function?

It turns the function into a generator: calling the function returns a generator object, and each yield pauses the function and produces one value to the caller.

2. What is the difference between yield and return in Python?

return finishes the function and gives one result; yield pauses the function, hands off one value, and keeps local state so the function can resume on the next step.

3. What happens when you call a generator function?

The function body does not run immediately—you get a generator object. Values are produced when you iterate with for or call next() on that object.

4. Can you iterate a generator more than once?

No—a generator is exhausted after one full pass. If you need to traverse the sequence again, build a list or create a new generator.

5. What is yield from used for?

It delegates to another generator or iterable, yielding every item from it without writing an explicit inner loop—useful for flattening nested structures.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …