In addition to sequence operations and list methods, Python includes a more advanced operation known as a list comprehension expression, which turns out to be a powerful way to process structures like our matrix. Suppose, for instance, that we need to extract the second column of our sample matrix. It’s easy to grab rows by simple indexing because the matrix is stored by rows, but it’s almost as easy to get a column with a list comprehension:
>>> col2 = [row[1] for row in M] # Collect the items in column 2 >>> col2 [2, 5, 8] >>> M # The matrix is unchanged [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
List comprehensions derive from set notation; they are a way to build a new list by running an expression on each item in a sequence, one at a time, from left to right. List comprehensions are coded in square brackets (to tip you off to the fact that they make a list), and are composed of an expression and a looping construct that share a variable name (row, here). The preceding list comprehension means basically what it says: “Give merow[1]for each row in matrixM, in a new list.” The result is a new list containing column 2 of the matrix.
List comprehensions can be more complex in practice:
>>> [row[1] + 1 for row in M] # Add 1 to each item in column 2 [3, 6, 9]
>>> [row[1] for row in M if row[1] % 2 == 0] # Filter out odd items [2, 8]
The first operation here, for instance, adds 1 to each item as it is collected, and the second uses anifclause to filter odd numbers out of the result using the%modulus expression (remainder of division). List comprehensions make new lists of results, but can be used to iterate over any iterable object—here, for instance, we’ll use list comprehensions to step over a hardcoded list of coordinates, and a string:
>>> diag = [M[i][i] for i in [0, 1, 2]]#Collect a diagonal from matrix >>> diag [1, 5, 9] >>> doubles = [c * 2 for c in 'spam']# Repeat characters in a string >>> doubles ['ss', 'pp', 'aa', 'mm']
List comprehensions are a bit too involved for me to say more about them here. The main point of this brief introduction is to illustrate that Python includes both simple and advanced tools in its arsenal. List comprehensions are an optional feature, but they tend to be handy in practice, and often provide a substantial processing speed advantage. They also work on any type that is a sequence in Python, as well as some types that are not. You’ll hear more about them later in this book.