Type for search...
codete basics of python dictionary comprehension list comprehension generator expression main 44644e82b7
Codete Blog

Python Basics: Generator Expressions & Comprehensions

codete logo 41a83d4d26

06/10/2021 |

8 min read

Codete

One of the things developers love about Python is the fact that its syntax is so simple and concise. Python code is almost as easy to read as plain English. Python’s most distinctive features, such as dictionary comprehension, list comprehension, and generator expression are the source of this elegance. Developers can use these three methods to create powerful functionalities within a single line of code. 

However, many software engineers still struggle to take full advantage of some more advanced features of list comprehension in Python. And others tend to use this too much and end up with code that is harder to read by others and less efficient. 

In this article, I dive deep into list comprehension, dictionary comprehension, and generator expression to show you what they are, how they work, and what potential trade-offs come with using these features. 

 

Table of contents:

  1. List and dictionary comprehensions in Python: the basics
  2. Python dictionary comprehension, list comprehension, and generator expression - what do you need to know
  3. Wrap up

List and dictionary comprehensions in Python: the basics

In Python, dictionaries are used to store elements - just like you would in a regular list. But instead of accessing these elements with the help of an index, what you do is assign a fixed key to a value and then access it using that key. The key-value pair might sometimes be a better data structure than a list for some kinds of problems. For example, dictionaries are a common feature used by data scientists. 

Note that all the keys in a dictionary need to be hashable. Hashing is the process of running an item through a particular kind of function called the hash function in Python. It returns a unique output for a unique input value. Just to give you an example, floating-point numbers, strings, and integers are all hashable. List, dictionaries, and sets aren’t.

 

So, why use comprehensions in Python?

Good comprehension helps to develop code that is more expressive and easier to read. The primary thing you need to remember when creating a comprehension construct is to never allow it to become too complex – to the point where you’re not too sure about what exactly they’re doing anymore.

Dictionary comprehension refers to a method for turning one dictionary into another one. During this kind of transformation, you can conditionally include the items from the original dictionary into the new one.

Dictionary comprehensions come in handy if you want to substitute for loops or lambda functions in Python. Not all for loops can be written as dictionary comprehension, but all dictionary comprehension can be written with a for loop. 

Python dictionary comprehension, list comprehension, and generator expression - what do you need to know

List comprehension

This feature offers a more compact and elegant method for building a list than for loops.

What exactly is a for loop? In Python, a for loop is used to handle repetitive programming tasks. You can use it to iterate over a sequence such as a list, dictionary, or string. Here’s an example of a for loop to help you understand how it works:

animals = ['cat', 'dog', 'lion']
for animal in animals:
print(animal)

A for loop takes the first element of the fragment and checks whether it exists. If it does, the for loop performs the required action – in our example, it’s printing. The loop starts again and looks for the next element. If it discovers that this element exists, it carries out the action again. This is repeated until the loop can’t find any more elements, and it ends. 

Ok, back to list comprehension.

You can use it to create lists from an existing list. Developers construct list comprehensions from brackets that contain the expression followed by a for clause. Optionally, the for or if clause can come next. 

Here is an example to show you how it works:

x = [i for i in range(10)]

This generates the following result:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

It’s far more concise and readable than its for loop equivalents. 

 

Dictionary comprehension

As I explained before, dictionary comprehensions work very similarly to list comprehensions – only for dictionaries. They offer an elegant way for building a dictionary from an iterable or transforming one dictionary into another. 

What is the syntax of dictionary comprehension? It’s very similar to the one you use for list comprehensions (more on that later on). However, you need to include the key-value pair in the expression. Here’s an example that shows you how it works:

{i: i+10 for i in range(4)}

The return value will be as follows:

{0: 10, 1: 11, 2: 12, 3: 13}

You can follow that basic syntax with an additional for or if clause if you need it. Dictionary comprehension is a powerful alternative to for loops and lambda functions. 

More often than not, for loops or nested for loops can become very complicated and, as a result, become very confusing for the team. Dictionary comprehensions, on the other hand, provide a compact way of writing the same code, which makes it easier to read and understand by developers.

 

Generator expressions

Finally, we have generator expressions - another high-performance method for writing code in Python. Generator expressions are far more efficient than traditional class-based iterators. In Python, class iterators are often verbose and require a lot of overhead from teams. Generators can perform the same function while reducing the overhead. And developers find creating generators relatively easy. 

All you need to do is define a normal function with a yield statement rather than a return statement. The yield statement pauses the function and saves its local state so that successive calls can continue from where it left off. 

Here’s how generators work: 

  • When you call a generator function, it doesn’t execute instantly but instead returns a generator object.
  • The code won’t execute until next() is called on that generator object.
  • When that happens, the control is passed temporarily to the caller, and the function is paused.
  • Local variables and their execution states will always be stored between calls.
  • Stop iteration will be raised automatically once the function is complete.

 

Generator expressions allow developers to build generators very quickly, without even having to use the yield keyword. They’re much more concise than generator functions. 

Here’s an example: 

g = (x**3 for x in range(20))

What is the difference between generator expressions and list comprehensions?

If you take a look at these two, you might notice that their syntax is very similar. The only difference here is that they use round parentheses as opposed to square brackets. 

A generator expression can be written in the following way:

(i ** 2 for i in range(10) if i % 2 == 0)

Now compare it to list comprehensions which are written as follows:

[i ** 2 for i in range(10) if i % 2 == 0]

However, the type of data they return is completely different. List comprehensions return the entire list, and the generator expression returns only the generator object. The values will be the same as those in the list, but they will be accessed one at a time by using the next() function. 

This is what makes list comprehensions faster than generator expressions. That might not be the case if the size of the data being processed is larger than the available memory, though. 

Since generator expressions produce value on-demand - contrary to list comprehensions that require memory for producing the entire list - generator expressions are more memory-efficient. It makes sense to use generator expressions if you’re working with large data sets and don’t need all of the results delivered to you at once. 

Also, use generator expressions if you would like to avoid allocating memory to the results that will be produced. Another good use case for generator expressions is representing infinite streams of data since only one item will be produced at a time. That way, you eliminate the problem of storing an infinite streaming memory. 

Wrap up

Python’s for loops come in handy for dealing with repetitive tasks, but there are other options that Python grants to developers that help you achieve the same results - only faster and more efficiently. List and dictionary comprehensions are a powerful alternative to for loops and lambda functions. They make code more concise and easier to read.

However, it’s key that developers never let them become too complex to cross off all the benefits they chose them for in the first place. Similarly, generators and generator expressions provide teams with high performance and a simpler way of creating iterators. They might be similar to list comprehensions in their syntax, but they return value only when asked for that. Unlike list comprehensions, they don’t deliver the entire list. As a result, they consume less memory and are more suited for processing big data. 

Are you planning to use one of these constructs in your next Python project? Or do you have experience in using them for building real-life applications? Give us a shout-out in the comments; we look forward to learning how developers are taking advantage of these Python functionalities to build products today.

Rated: 5.0 / 1 opinions
codete logo 41a83d4d26

Codete

IT consulting and software development company. Since 2010, we’ve been supporting businesses worldwide in gaining competitive advantage by means of modern technology. We advise on digitalization, develop and implement high-quality solutions, and augment our clients’ teams with skilled software developers.

Our mission is to accelerate your growth through technology

Contact us

Codete Przystalski Olechowski Śmiałek
Spółka Komandytowa

Na Zjeździe 11
30-527 Kraków

NIP (VAT-ID): PL6762460401
REGON: 122745429
KRS: 0000696869

Offices
  • Kraków

    Na Zjeździe 11
    30-527 Kraków

  • Lublin

    Wojciechowska 7E
    20-704 Lublin

  • Berlin

    Wattstraße 11
    13355 Berlin

Copyright 2022 Codete