
As one of the most widely used "Pythonic" syntax in Python, you must have ever heard List Comprehension or have already used it frequently. It is almost a must-have section in various Python elementary tutorials. However, did you know that there are actually 4 types of "comprehension" in Python rather than only for the lists? You may also have heard or ever used Dictionary Comprehension, but might not for the set and generator.
In this article, I’ll introduce all the 4 types comprehensions in Python with examples. In the last section, I also want to give an example to show you when not to use comprehensions for better readability. Use it with care, please!
1. List Comprehension

This is definitely the most commonly used one in Python. You’ll see them everywhere. The basic syntax is as follows:
my_list = [<expression> for <item> in <iterable> if <condition>]
Here, the expression
may be exactly the same as item
which means that we don’t want to do anything to the items and just have the as-is.
The condition
is optional. Only use it when you want to do a filter.
So, basically:
expression = item
when you want to leave theitem
unchanged.expression != item
when you want to apply some logic to modifyitem
.condition
will help to filter theiterable
which may return feweritems
.condition
is optional so that if it is suppressed the length of theiterable
must be equal tomy_list
.
Let’s have an example for demonstration. Suppose we have a list with just 1–10 integers.
my_list = [1,2,3,4,5,6,7,8,9,10]
What we want to do is to have a new list with the numbers in my_list
- Filter the number to have only even numbers (use
condition
) - With the filtered number, plus one to it before it is pushed into the new list (use
expression
)
new_list = [number + 1 for number in my_list if number % 2 == 0]

Very concise and readable! What if we don’t use List Comprehension? Here is an example.
new_list = []
for number in my_list:
if number % 2 == 0:
new_list.append(number + 1)

It also has pretty good readability, but less concise. Also, we have to initialise the new_list before anything else.
So, which one do you like? I think the answer is obvious for most of us
2. Dictionary Comprehension

The name, "Something" Comprehension, is actually depending on the output object type rather than the iterable that is used in the comprehension. Therefore, a Dictionary Comprehension will generate a Dictionary.
The basic syntax is as follows:
my_dict = [<key>:<value> for <item> in <iterable> if <condition>]
Please be noticed that the key
and value
here can be expressions with or without item
.
Let’s say that we have a list of dictionary objects which contain employee names, age and job titles.
persons = [
{
'name': 'Alice',
'age': 30,
'title': 'Data Scientist'
},
{
'name': 'Bob',
'age': 35,
'title': 'Data Engineer'
},
{
'name': 'Chris',
'age': 33,
'title': 'Machine Learning Engineer'
}
]
The requirement is to get all the employees having their title contains the string "Data". So, we can call them "data employees".
Also, we’re not interested in the employees’ age, so that we want to have such a dictionary with the employee names as the keys and their job titles as the value.
This time, let’s write the code without dictionary comprehension first.
data_employees = {}
for p in persons:
if 'Data' in p['title']:
data_employees[p['name']] = p['title']

Again, we have to initialise an empty dictionary at the beginning. Inside the for-loop, we will put the if-condition to filter the employees’ job title. Finally, we need to make sure that the structure of the new dictionary obeys the requirements.
With Dictionary Comprehension, we can put all these in one line and even in prove its readability.
data_employees = {p['name']:p['title'] for p in persons if 'Data' in p['title']}

Besides concise, I would say that the Dictionary Comprehension is even more readable.
3. Set Comprehension

Yep, there is a Set Comprehension syntax in Python, which many people don’t know. In fact, the only difference between a Set Comprehension and a List Comprehension is that the former uses curly braces {}
rather than square brackets []
.
The syntax is as follows:
my_set = {<expression> for <item> in <iterable> if <condition>}
Are you confusing it with Dictionary Comprehension? The difference between these two is that the Set Comprehension doesn’t have the key:value
pair, but only one expression
.
Now, let reuse the employee list used in the previous section.
Suppose we are not using Set Comprehension.
data_employees_set = set()
for p in persons:
if 'Data' in p['title']:
data_employees_set.add(p['name'])

Then, let’s use it.
data_employees_set = {p['name'] for p in persons if 'Data' in p['title']}

Keep in mind that the difference between a set and a list is that the items in a set cannot be repeated and not in order
4. Generator Comprehension

Last but not the list, Generator Comprehension is also not known by most of the people. The generator is a quite unique syntax in Python, it is usually generated from a function with yield
keyword rather than Python.
For example, let’s use the same number list and requirements from the List Comprehension section. We can define a function to make a generator for us.
def even_generator(numbers):
for n in numbers:
if n % 2 == 0:
yield int(n/2)
eg = even_generator(my_list)
A generator can be iterated by its built-in function next()
. So, we can keep getting the next value of the generator by calling print(next(eg))
.

In fact, all these can be done using Generator Comprehension. The only difference between Generator Comprehension and List Comprehension is that the former uses parentheses.
my_gen = (<expression> for <item> in <iterable> if <condition>)
Yes, we even don’t need the yield
keyword! Let’s give it a try.
eg = (int(number/2) for number in my_list if number % 2 == 0)

That’s it, all done.
5. Nested Comprehension

We have explored all the 4 types comprehensions in Python. They are really nice syntax in Python. However, as far as I know, a lot of learners tend to use them too frequently once they understand how to use the comprehensions. This might not be a good thing.
We usually like to use comprehensions to write more concise and readable codes. However, sometimes the logic is relatively complex, it will hurt the readability if we use the comprehensions.
One of the typical cases is nested comprehensions.
For example, we want to print a multiplication table from 1–10. Here is a normal way to implement this. Of course, without any list comprehensions.
for row in range(1, 10):
for col in range(1, row+1):
print(f'{col}x{row}={row*col} t', end='')
print("")

A few things to be noticed, it is fairly easy for us to control the output format because we can have multiple expressions inside the for-loop. For example, we can use the end=''
argument in the print()
function to prevent it output a new line.
If we use List Comprehension to implement this, of course we can, but lots of stuff will be squeezed in one line of code which really damage the readability.
print('n'.join([''.join([f'{col}x{row}={row*col} t' for col in range(1, row + 1)]) for row in range(1, 10)]))

I bet no one can understand the code above very easily.
Basically, I’m not suggesting to abandon nested comprehensions. Sometimes, it is OK if the logic is really simple. However, it worth to think twice whether we really need to use the comprehensions if we meet such a case that needs nested comprehensions.
Summary

In this article, I have introduced all the 4 types of comprehensions in Python – List, Dictionary, Set and Generator Comprehension. Most of the time, they are very elegant, concise and even can improve the readability of our code. That is the so-called "Pythonic".
However, we also need to pay attention not to abuse it. When the logic is not simple, the comprehension can hurt the readability. In many cases that need nested comprehensions, we need to ask ourselves: Should I write the logics in nested comprehensions?
Hope you enjoy the reading. Happy coding!
If you feel my articles are helpful, please consider joining Medium Membership to support me and thousands of other writers! (Click the link above)