top of page

Generators in Python




Generators in Python


Generators are a type of iterable in Python that generate their contents on-the-fly, making them more efficient when working with large datasets. Unlike lists or tuples, generators do not store their contents in memory, which makes them more memory-efficient.

How to create a generator


You can create a generator using a simple function with the yield keyword. When the function is called, it returns a generator object, which can be iterated over using a for loop or other methods.

Here's an example of a simple generator function that generates the square of a number:


def square_generator(n):
    for i in range(n):
        yield i ** 2


To use this generator function, you simply call it with an argument, like so:


for square in square_generator(5):
    print(square)

This will output:


0
1
4
9
16

Here are a few more examples of generators in Python:


Example 1: Generating prime numbers

def primes():
    yield 2
    prime = 3
    while True:
        is_prime = True
        for i in range(2, int(prime ** 0.5) + 1):
            if prime % i == 0:
                is_prime = False
                break
        if is_prime:
            yield prime
        prime += 2

This generator continuously generates prime numbers, starting with 2. It uses a while loop to check each odd integer for primality, and yields each prime it finds.


Example 2: Generating permutations


def permutations(iterable, r=None):
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    indices = list(range(n))
    cycles = list(range(n, n-r, -1))
    yield tuple(pool[i] for i in indices[:r])
    while True:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i+1:] + indices[i:i+1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                yield tuple(pool[i] for i in indices[:r])
                break
        else:
            return

This generator generates all possible permutations of a given iterable. It uses a recursive algorithm to generate the permutations and yield each one.


Example 3: Generating an infinite sequence of integers

def integers():
    i = 0
    while True:
        yield i
        i += 1

This generator generates an infinite sequence of integers, starting with 0. It simply yields each integer as it is generated, using a while loop to continue indefinitely.


Benefits of using generators


One of the main benefits of using generators is memory efficiency. Since generators do not store their contents in memory, they can be used to generate large datasets without causing memory issues. This is particularly useful when working with data that does not fit into memory, such as large files or data streams.

Generators can also be used to create infinite sequences, such as an infinite sequence of random numbers or an infinite sequence of Fibonacci numbers. This is not possible with lists or other types of iterables, which have a fixed length.

Another advantage of using generators is that they can be used to create pipelines of data processing functions. In this approach, each function in the pipeline is a generator that processes the data and passes it to the next function in the pipeline. This allows you to write modular, composable code that is easy to read and maintain.


Conclusion


Generators are a powerful tool in Python that can be used to efficiently generate large datasets, create infinite sequences, and build pipelines of data processing functions. By using generators, you can save memory and improve the performance of your code.

bottom of page