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.
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]
>>> [(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)]
>>> [(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)]
>>> [i for i in range(1, 5) for j in range(i)] [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
>>> vec = [-4, -2, 0, 2, 4] >>> [abs(x) for x in vec] [4, 2, 0, 2, 4]
>>> 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]]
>>> 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]
List comprehensions are typically faster than their loop-based counterparts, often without fine-tuning. The below tests are taken directly from the above examples.
n = int(10000) squares = [([(x**2, y**2) for x in range(n) for y in range(n)])]
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.