How Python Generators Can Supercharge Your Code and Save Your Memory!

Jahidul Hasan Hemal
4 min readApr 19, 2023

--

AI Art using Midjourney

Python is a powerful programming language that offers a variety of features and functionalities to developers. One such feature is the concept of generators. Generators are a powerful way to create iterators in Python, allowing developers to efficiently generate and manipulate large sequences of data.

In this blog post, we’ll explore the concept of generators in Python, and why you should consider using them in your development projects.

What are Python Generators?

In Python, a generator is a function that can be used to produce a sequence of values, one at a time, on demand. The values are generated using the yield keyword, which allows the function to produce a value and then suspend execution until the next value is requested. Generators are similar to regular functions, but instead of returning a value and terminating, they can be resumed from where they left off when a new value is requested.

Why Use Python Generators?

There are several reasons why you should consider using generators in your Python projects:

  1. Memory Efficiency

One of the main advantages of generators is their memory efficiency. Suppose you want to generate a large sequence of numbers and store them in a list. Using a list comprehension, you would write code like this:e

numbers = [i**2 for i in range(1000000)]

This code generates a list of one million numbers, which could take up a lot of memory. However, using a generator expression, you can generate the same sequence of numbers without creating a list:

numbers = (i**2 for i in range(1000000))

This code creates a generator that produces the same sequence of numbers, but without storing them all in memory at once. This is especially useful when working with large datasets that don’t fit into memory.

2. Lazy Evaluation

Another advantage of generators is their ability to perform lazy evaluation. Suppose you have a function that takes a long time to compute and you want to generate a sequence of values using that function. Using a list comprehension, you would write code like this:

values = [expensive_function(i) for i in range(1000000)]

This code generates a list of one million values by calling the expensive_function for each value. However, using a generator, you can generate the same sequence of values lazily, so that expensive_function is only called when each value is requested:

def generate_values():
for i in range(1000000):
yield expensive_function(i)
values = generate_values()

This code creates a generator that produces the same sequence of values, but only calls expensive_function when each value is requested. This is especially useful when working with functions that are computationally expensive or when generating values from an external source.

3. More Readable Code

Generators can also make your code more readable. Suppose you have a list of strings and you want to generate a new list that contains only the strings that start with the letter “A”. Using a for loop and an if statement, you would write code like this:

new_list = []
for string in old_list:
if string.startswith("A"):
new_list.append(string)

This code works, but it can be a bit verbose. Using a list comprehension, you can express the same operation in a more concise way:

new_list = [string for string in old_list if string.startswith("A")]

This code is more readable, but it still generates a list that may take up a lot of memory. Using a generator expression, you can express the same operation even more concisely:

new_list = (string for string in old_list if string.startswith("A"))

This code creates a generator that produces the same sequence of strings, but without storing them all in memory at once. This is especially useful when working with large datasets or when chaining multiple generator functions together.

4. Generators Are Composable

Generators can also be used to create pipelines of operations that are composable. Suppose you have a list of dictionaries and you want to generate a new list that contains only the values of the “name” key for the dictionaries where the “age” key is greater than 18. Using a for loop and an if statement, you would write code like this:

new_list = []
for dictionary in old_list:
if dictionary["age"] > 18:
new_list.append(dictionary["name"])

This code works, but it can be a bit verbose. Using a list comprehension, you can express the same operation in a more concise way:

new_list = [dictionary["name"] for dictionary in old_list if dictionary["age"] > 18]

This code is more readable, but it still generates a list that may take up a lot of memory. Using a generator expression, you can express the same operation even more concisely:

new_list = (dictionary["name"] for dictionary in old_list if dictionary["age"] > 18)

This code creates a generator that produces the same sequence of names, but without storing them all in memory at once. You can then chain multiple generators together to create a pipeline of operations that are composable, like this:

new_list = (dictionary["name"] for dictionary in old_list if dictionary["age"] > 18)
new_list = (name.upper() for name in new_list)
new_list = (name.strip() for name in new_list)

This code creates a pipeline of three generators that filter the original list, convert the names to uppercase, and strip whitespace from the names. This pipeline is composable, meaning you can easily add or remove operations as needed.

Python generators are a powerful tool that can make your code more memory-efficient, readable, and composable. They allow you to generate sequences of values lazily, so that values are only computed when needed. They also allow you to chain multiple generators together to create pipelines of operations that are composable. By using generators in your Python code, you can write more efficient, readable, and maintainable code.

--

--

Jahidul Hasan Hemal

A goddamn marvel of modern science. An open-source enthusiast and an optimist who loves to read and watch movies and is trying to learn how to write.