Believemy logo purple

Understanding yield in Python: the complete guide

yield transforms a function into a generator. This allows the function to return values successively, while maintaining the function's internal state.
Believemy logo

The yield keyword in Python allows you to create what we call a generator function.

Unlike return which returns a value once and for all, yield suspends the execution of the function and preserves its state to resume where it left off.

This little mechanism makes yield ideal for:

  • Iterating over large amounts of data;
  • Creating lazy data streams (the famous lazy-loading);
  • Improving memory performance.

In summary, yield transforms a classic function into a generator, capable of producing values on the fly.

 

Yield syntax and example

Yield syntax

The syntax of yield is extremely simple:

PYTHON
def my_function():
    yield value

It's used exactly like the return keyword! 😉

Each time execution reaches the yield keyword, it returns a value to the caller, but does not terminate the function. On the next call, it resumes right after the yield.

A function containing at least one yield automatically becomes a generator.

 

Example of using yield

Let's take a small example to better understand how yield works!

Imagine a pizzeria that prepares pizzas one by one. Each pizza is "yielded" as soon as it's ready, instead of waiting for all of them to be finished.

PYTHON
def make_pizzas():
    yield "🍕 Margherita ready!"
    yield "🍕 Queen ready!"
    yield "🍕 4 Cheese ready!"

for pizza in make_pizzas():
    print(f"Order sent: {pizza}")

Result:

PYTHON
Order sent: 🍕 Margherita ready!
Order sent: 🍕 Queen ready!
Order sent: 🍕 4 Cheese ready!

This type of approach is perfect for simulating queuing systems, data streaming, or batch production. Each yield allows sending data as soon as it's available, without blocking the execution of the rest of the program.

 

Understanding generators in Python

Classic function vs generator: what are the differences?

A classic function executes its code, returns a value with return and terminates immediately.

A generator function uses yield. It:

  • Can produce multiple values successively;
  • Does not terminate its execution at each yield;
  • Resumes where it was interrupted.

Let's take this comparative example:

PYTHON
# Classic function
def classic():
    return [1, 2, 3]

# Generator
def generator():
    yield 1
    yield 2
    yield 3

The generator doesn't create an entire list in memory, it sends each value on demand.

 

A "lazy" behavior

The yield keyword enables lazy evaluation: values are only calculated when they are requested.

This allows to:

  • Reduce memory consumption;
  • Handle continuous or very large streams (thousands of elements);
  • Improve streaming performance.

To better understand how it works, let's take an example again. This time with an infinite number generator.

PYTHON
def infinite_numbers():
    i = 1
    while True:
        yield i
        i += 1

gen = infinite_numbers()
print(next(gen))  # 1
print(next(gen))  # 2

This function never stops, but consumes almost no memory! 😬

It remembers its last result to increase it by one at each function call: that's the whole point of a generator.

 

yield and yield from: different but complementary

In Python, the yield keyword allows producing values one by one in a generator function.

But in some cases, when this function must in turn call another generator, it can quickly become verbose and repetitive.

That's where yield from comes into play.

Using yield from for simplified delegation

With yield from, you can directly delegate iteration to a sub-generator or to any iterable (list, tuple, etc).

Here's a small example:

PYTHON
def fruits():
    yield from ["🍎", "🍌", "🍓"]

def vegetables():
    yield from ["🥦", "🥕"]

def market():
    yield "Market start"
    yield from fruits()
    yield from vegetables()
    yield "Market end"

for item in market():
    print(item)

We create here three generators:

  1. fruits - contains the market fruits;
  2. vegetables - contains the vegetables;
  3. market - contains the functioning of our market (well, obviously, it's an example 😉).

Here's its result:

CONSOLE
Market start  
🍎  
🍌  
🍓  
🥦  
🥕  
Market end

Each generator is modular, and yield from allows us to compose them easily without making the logic heavier.

Finally, what you need to remember is that yield is made to manually produce values.

On its side, yield from allows easily integrating other generators, which allows us to decompose our code, to make it more maintainable.

 

Summary table

Let's summarize all this in a small table.

Aspectyieldyield from
Produces a single value✅ Yes❌ No
Delegates to an iterable❌ Requires a loop✅ Yes
Compact syntax❌ Less clear for delegation✅ Very readable
Used forSimple generatorsSub-generators

 

Frequently asked questions about yield

Here are the most frequent questions when you're starting with yield in Python.

What is the difference between yield and return?

return terminates the function. yield suspends and resumes later.

 

Can you do a break in a yield?

Yes, like in any loop.

 

Is it compatible with async?

No. For asynchronous, we use async def and await.

 

Can you nest multiple yield?

Yes. Even in nested loops and conditions.

 

Where can I learn Python?

On a complete course, like ours! 😋

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.