Initially introduced by Barry Warsaw on PEP-202, comprehensions became part of the Python language in version 2.0 almost twenty years ago. This language feature enables a beautiful and convenient way to work with iterables. By using comprehensions the code is written in a more declarative and concise way. I think of it as an elegant way of Python’s for implementing a well-known Mathematics notation: { x2 | x ∈ ℕ }.
Let’s look at a code example. The lines of code below add the square numbers from 0 to 9 to a list and print them.
squares = []
for x in range(10):
squares.append(x ** 2)
print(squares)
List comprehensions
The same functionality can be re-written using list comprehensions with the following syntax: [ expression for * *element** in iterable ]
squares = [x ** 2 for x in range(10)]
print(squares)
Using conditionals statements with list comprehensions
The initial presented code is now modified below using a conditional statement that only adds the even square numbers to the list.
squares = []
for x in range(10):
if (x % 2 == 0):
squares.append(x ** 2)
print(squares)
This can be re-written with the following syntax: [ expression for element in iterable if condition ]
squares = [x ** 2 for x in range(10) if (x % 2 == 0)]
print(squares)
Dictionary comprehensions
In PEP-274 a proposal for similar syntactical extension for dictionary objects instead of lists is introduced. This one is called “Dictionary Comprehension”. And you can see an example below using a conditional statement.
squares = {x: x**2 for x in range(10) if (x % 2 == 0)}
print(squares)
Set comprehensions
A set is an unordered and mutable collection of items. All its elements are unique (no duplicates) and immutable. Set comprehensions are created the same way as dictionary comprehensions.
numbers = [0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 8, 9, 9, 9]
squares = {x**2 for x in numbers}
print(squares)
Generator comprehensions
They are similar to the examples above. The main difference is that they do not allocate memory for the expected type but generate one item at a time. This results in better memory usage efficiency. See also PEP-289.
squares = (x**2 for x in range(10) if x % 2 == 0)
print(squares)
for s in squares:
print(s)
TLDR
Comprehensions are in my humble opinion an awesome feature of Python, supported in both versions 2.x. and 3.x. As you can see, they provide a clean and concise way to avoid nested loops, lambda functions or even filter() or/and map functions.