As list comprehensions are an incredibly powerful way of processing lists in Python, they deserve a special mention. This short session aims to do just that.
All list comprehensions have one thing in common: They start with a list of items, and return a new list based on those items.
The simplest list comprehensions involve doing something simple with each element in the list. For instance if we have words, we could use a list comprehension to make them all uppercase:
words = ["The", "big", "bad", "Wolf"]
uppers = [ word.upper() for word in words ]
Don't confuse the brackets in the second line with the literal list construction of the first line. The brackets on the second line form a list comprehension, which in its simplest form has the following shape (where the angle-bracketed elements are variable):
[<expression> for <x> in <list>]
This syntax expresses that a new list should be created by evaluating the expression
once for each possible value of x
taken from the list
.
Every list comprehension can be done via a for-in
loop, just not as elegantly. So the above list comprehension could be written as:
uppers = []
for word in words:
uppers.append(word.upper())
Whenever you see a list comprehension, it essentially corresponds to some analogous "for" expression.
Here is a variation that replaces each word with a pair of the word in capitals and its length:
words = ["The", "big", "bad", "Wolf"]
pairs = [
[word.upper(), len(word)]
for word in words
]
# Reading back the lengths from those pairs:
lengths = [ p[1] for p in pairs ]
Practice problem: Work the same thing out via a "for" loop.
List comprehensions are often just the first step in further processing. For example, we could use a list comprehension to get the lengths of the words in the list, then use the sum
function to add up those lengths:
lengths = [len(word) for word in words]
totalLength = sum(lengths)
One neat feature of list comprehensions is that they allow you to filter the results in a suitable way. So imagine we wanted to collect all numbers from 1 to 20 that are odd, and square them. We could write:
numbers = []
for n in range(1, 21):
if n % 2 == 1:
numbers.append(n * n)
Instead we could do this via a list comprehension:
numbers = [ n * n for n in range(1, 21) if n % 2 == 1 ]
# Or expanded:
numbers = [
n * n
for n in range(1, 21)
if n % 2 == 1
]
"art"
will become "art 3"
.We will look at two more complicated examples. The first involves nested loops. Imagine for instance that we had a list of lists of numbers, and we wanted to flatten it all into a single list. One way to do this would be via a nested loop, the other would be via a list comprehension:
nums = [[1, 2, 3], [4, 5, 6]]
# Via nested loop
result = []
for row in nums:
for n in row:
result.append(n)
# Via list comprehension:
result = [
n
for row in nums
for n in row
]
So each subsequent for-in
generator will happen within each case of the previous generators. So for every row
in the nums
list and every number n
in that row
, we read that number.
Here is a more complicated example for finding all "Pythagorian triples" up to 100. A Pythagorian triple is three integers x, y, z such the squares of x and y add up to the squares of z. Here is how that might look via a list comprehension:
triples = [
[x, y, z]
for x in range(1, 101)
for y in range(1, 101)
for z in range(1, 101)
if x*x + y*y == z*z
]
A list comprehension can actually produce a dictionary instead. Here is an example where for each string in the list of words earlier we create a key in the dictionary, whose value is the length:
{
word: len(word)
for word in words
}
You provided a JSON representation of students earlier. It looked in general like so:
{
"login": "...",
"first": "...",
"last": "...",
"courses": [
{
"dept": "CS",
"name": "...",
...
},
...
]
}
(login, number)
for each student and the number of courses the student has.(login, coursename)
for each course a student is enrolled in.Starting with a list of numbers, use a list comprehension to produce a list of strings, each string consisting of a number of asterisks equal to the corresponding number (multiplying a string with a number returns that string replicated that many times).