Language: EN

generadores-en-python

What are and how to use Generators in Python

In Python, generators are a tool that allows generating sequences of data, focused with efficiency as the goal.

To do this, unlike lists, generators do not store all elements in memory, but produce them on the fly.

This makes them very useful for working with large datasets or continuous data streams, as elements are generated only when needed (and only if needed).

Their main advantage is that they are much more memory efficient than lists (because they do not store all elements in memory at once)

What are generators

A generator is a function that uses the yield keyword instead of return (yield could be interpreted as “give way”).

The yield keyword allows a function to produce a value, but at the same time “remember” its state. This allows the execution to be resumed at that point on the next call.

Let’s see it with an example,

def simple_generator():
    yield 1
    yield 2
    yield 3

When simple_generator() is called, the code inside the function does not execute immediately. Instead, it returns a generator object that can be iterated to produce the values.

The created generator object is not callable by itself. Instead, “the next value is requested” with next(). For example like this,

gen = simple_generator()
print(next(gen))  # Output: 1
print(next(gen))  # Output: 2
print(next(gen))  # Output: 3

In this example

  • We use the generator function simple_generator() to create a generator object gen
  • next(gen) is used to get the next value produced by the generator
  • When there are no more values to produce, the generator raises a StopIteration exception

Generators with Loops

Most generators are created using loops to produce a sequence of values.

def count_to(n):
    counter = 1
    while counter <= n:
        yield counter
        counter += 1

This generator function

  • Starts by returning counter with a value of 1
  • Each time the function is called, it “wakes up” in the while loop. It increments the value, loops, and returns the new counter
  • When counter reaches 5, the loop ends, and the sequence finishes.

It is also very common for the use of generators to be done from a loop. For example, it is very common to use them with for.

for number in count_to(5):
    print(number)

# output: 1 2 3 4 5

Combined Generators

Generators can be nested to handle more complex sequences.

def nested_generator():
    yield from range(3)
    yield from range(10, 13)

for number in nested_generator():
    print(number)

# output: 0 1 2 10 11 12

In this example, yield from delegates the production of values to another generator or iterable.

  • First, the function returns the values generated by range(3)
  • When it finishes, it supplies the values from range(10, 13)
  • When both finish, the sequence ends

Generators with Expressions

Python also allows creating generators using a syntax similar to list comprehensions, known as “generator comprehension”.

gen = (x**2 for x in range(10))

for number in gen:
    print(number)

# output: 0 1 4 9 16 25 36 49 64 81