User Tools

Site Tools


python3:list_comprehensions

List Comprehensions

List comprehensions are used for creating lists from existing lists and other iterable structures. List comprehensions typically follow formatting similar to set-builder notation in discrete mathematics.

Syntax

Consider the following illustrative Python3 example for generating a list of squares:

>>> sq = []
>>> for i in range(10):
...  sq.append(i**2)
... 
>>> sq
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

The same could be achieved in the following list comprehension1)

>>> [i**2 for i in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Example Functionality

Multiple Loops

>>> [(x**2, y**2) for x in range(3) for y in range(3)]
[(0, 0), (0, 1), (0, 4), (1, 0), (1, 1), (1, 4), (4, 0), (4, 1), (4, 4)]

Conditionals

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1,3), (1,4), (2,3), (2,1), (2,4), (3,1), (3,4)]

Repetitions

>>> [i for i in range(1, 5) for j in range(i)]
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

Processing non-range() iterables

>>> vec = [-4, -2, 0, 2, 4]
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]

Creating a double list

>>> n = 3
>>> [[i for i in range(j*n, j*n+n)] for j in range(n)]
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]

Flattening a double list

>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Benchmarks

List comprehensions are typically faster than their loop-based counterparts, often without fine-tuning. The below tests are taken directly from the above examples.

square_comprehension.py
n = int(10000)
squares = [([(x**2, y**2) for x in range(n) for y in range(n)])]
square_loop.py
n = int(argv[1])
 
squares = []
 
for i in range(n):
    for j in range(n):
        squares.append((i**2, j**2))
n square_comprehension.py2) square_loop.py
500 .1864s .2152s
1000 .7104s .8147s
1500 1.572s 1.8304s
2000 2.7992 3.28s

Note that both of the above examples require storage of (potentially) millions of tuples. Many problems will not necessarily require storage of this many values in memory, but instead iterating over them. In such an instances iteration using for loops or Generators may be advisable.

1)
Note that the list comprehension can also be constructed by considering the set-builder construction for the same example:
{n2 | nZ ∧ 0 ≤ n ≤ 9 }.
While a full understanding of set-builder notation is not necessary for working with list comprehensions, in some instances they may lead to a more natural translation to list comprehensions than equivalent loop-based code.
2)
Python 3.5.2
python3/list_comprehensions.txt · Last modified: 2019/05/07 16:19 by jguerin