Python yield: Create Efficient Generators

Published on: June 3, 2026
Reading time: 6 minutes
Criação de geradores eficientes usando yield em Python

Have you ever felt your computer freeze while trying to process a huge list of data? That happens because, by default, Python tries to load all the information into RAM at once. To solve this efficiency problem, Python offers generators. Learning how to create efficient generators with yield in Python is a turning point for any developer who wants to write professional, fast code that uses fewer system resources. This guide covers everything from the basic concept to advanced applications of this powerful tool.

What are generators in Python?

Generators are a special type of iterable, just like lists or tuples. The key difference is that they do not store all their values in memory. Instead, they produce items one by one, on demand. Think of a box with a million marbles. A list would be like dumping all the marbles on your floor at once. A generator is like a machine that hands you one marble at a time, only when you ask for the next one.

This characteristic makes generators extremely useful for handling large datasets and improving Python performance. When you use generators, Python preserves the state of the function, allowing it to resume exactly where it left off on the next iteration.

The yield keyword: the engine of generators

To understand how to create efficient generators with yield, focus on the yield keyword. Unlike return, which ends a function’s execution and returns a value, yield pauses the function and saves its current state. When the function is called again, it resumes from the line immediately after the last yield.

Here is a simple example of a generator function:

Python
def simple_counter():
    yield 1
    yield 2
    yield 3

gen = simple_counter()
print(next(gen))  # Output: 1
print(next(gen))  # Output: 2

Calling the function does not execute the code immediately. It returns a generator object. Only when you use next() or a loop does the internal code start running until it finds the first yield.

Advantages of yield over lists

Three pillars justify using generators in your projects:

  • Memory efficiency: Since values are produced one at a time, you can process gigabyte files on a machine with limited RAM.
  • Lazy evaluation: Processing only starts when you actually need the data. If you stop reading halfway through, you have not wasted resources generating the rest.
  • Cleaner code: A generator often replaces complex class structures that implement iteration protocols (the __iter__ and __next__ methods).

According to the Python Software Foundation official documentation, generators are the most elegant way to implement iterators in a compact form.

Regular functions vs generator functions

In a regular function, when the interpreter hits return, the function’s call stack is discarded and all local variables are lost. In generator functions, state is preserved, including the values of local variables and the position of the last executed line.

Using yield to read large files

One of the most common use cases is reading heavy text files. If you try to read a 10GB log using .readlines(), your program will likely run out of memory. With yield, you read line by line safely.

Python
def read_large_file(path):
    with open(path, 'r') as file:
        for line in file:
            yield line.strip()

# Efficient usage
for line in read_large_file('big_data.csv'):
    process(line)

Working with infinite generators

A fascinating feature of generators is their ability to represent infinite sequences. Since values are not stored, you can create a generator that never stops, as long as your consuming loop has an exit condition.

Python
def infinite_fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

sequence = infinite_fibonacci()
for _ in range(10):
    print(next(sequence))

Generator expressions

Just like list comprehensions, Python offers generator expressions. The syntax is almost identical, but instead of square brackets [], you use parentheses ().

Python
# List Comprehension (uses memory)
my_list = [x **2 for x in range(1000000)]

# Generator Expression (efficient)
my_gen = (x **2 for x in range(1000000))

Generator expressions are ideal for passing data to functions that accept iterables, such as sum(), max(), or min(), without creating an intermediate list in RAM. To benchmark the speed difference, check how to measure Python code speed with timeit.

yield from: simplifying nested generators

Python 3.3 introduced the yield from syntax. It lets a generator delegate part of its operation to another iterable or generator. This avoids unnecessary for loops inside the function and makes code much more readable.

Python
def sub_process():
    yield 'A'
    yield 'B'

def main_process():
    yield 'Start'
    yield from sub_process()
    yield 'End'

print(list(main_process()))
# Output: ['Start', 'A', 'B', 'End']

When NOT to use generators

Although generators are powerful, there are situations where they are not the best choice:

  • Random access: You cannot access item [5] of a generator without iterating through the first four. If you need index-based access, use a list or tuple.
  • Data reuse: After consuming a generator, it is exhausted. If you need to read the same data multiple times, you must recreate the generator or store the results (which negates the memory benefit).
  • Operations that require the total size: The len() function does not work with generators because Python does not know how many items will be produced until the process ends.

Best practices and generator pipelines

Keep your generator functions focused on a single task. If a generator is processing data, filtering, and saving to a database all at once, split it into smaller generators connected in a pipeline. Follow the PEP 8 style guide for clean, readable code.

Python
data = read_large_file('sales.log')
clean_data = (line.upper() for line in data)
filtered_data = (line for line in clean_data if 'ERROR' in line)

In this pipeline, no processing happens until you try to read the first item from filtered_data. Each line flows through the system individually.

Frequently asked questions

What does yield do exactly in Python?

yield pauses a function’s execution and returns a value to the caller, but preserves the function’s state so it can continue from where it left off the next time it is called.

Can I use return and yield in the same function?

Yes, in Python 3 this is allowed. A return in a generator function raises a StopIteration exception and terminates the generator, optionally sending a final closing value.

How do I restart a generator that has finished?

Generators cannot be restarted. To iterate over the data again, you must create a new instance of the generator function.

Are generators faster than lists?

For small lists, the CPU time difference is minimal. For large volumes of data, generators are far superior in terms of memory consumption and startup time.

What happens if I call next() on an empty generator?

Python raises a StopIteration exception. You can handle this with a try/except block or use the next(gen, default_value) form to return a fallback value instead of raising an error.

Mastering yield lets you handle large volumes of data elegantly and professionally. By understanding how to create efficient generators in Python, you go from someone who just makes code work to a developer who cares about application scalability and conscious hardware usage.

Share:

Facebook
WhatsApp
Twitter
LinkedIn

Article content

    Related articles

    Uso do operador walrus para atribuições inline em Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python Walrus Operator (:=) Explained with Examples

    Learn how Python's walrus operator (:=) works for assignment expressions inside if, while, and list comprehensions, with practical examples and

    Ler mais

    Tempo de leitura: 3 minutos
    03/06/2026
    Geração de números aleatórios seguros usando secrets em Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Generate Secure Random Numbers in Python with secrets

    Learn how Python's secrets module generates cryptographically secure random numbers, tokens, and passwords using randbelow, token_hex, token_urlsafe, and compare_digest.

    Ler mais

    Tempo de leitura: 4 minutos
    01/06/2026
    Pattern matching com match case em Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python match-case: Pattern Matching Explained

    Learn how Python match-case works for structural pattern matching, including values, sequences, dictionaries, guards, and dataclasses with practical examples.

    Ler mais

    Tempo de leitura: 4 minutos
    30/05/2026
    Como resolver loop infinito que nunca termina em Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Why Does My Loop Never End? Find the Solution

    Find out why your Python loop never ends and learn how to fix infinite loops caused by missing increments, wrong

    Ler mais

    Tempo de leitura: 6 minutos
    29/05/2026
    Logo do Python com as palavras global e local
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python Variable Scope Explained Clearly

    Learn Python variable scope with clear examples of local, global, enclosing, built-in scope, LEGB rules, global, nonlocal, and common mistakes.

    Ler mais

    Tempo de leitura: 9 minutos
    28/05/2026
    Comparativo dos melhores cursos de Python para aprender programação
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    8 Best Python Courses for Beginners in 2026

    Compare the 8 best Python courses for beginners in 2026, including Academify, Alura, Udemy, Coursera, Codecademy, Harvard CS50, EBAC, and

    Ler mais

    Tempo de leitura: 7 minutos
    28/05/2026