Python for Programmers: Comprehensions
Welcome to the Comprehensions lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
We often need to transform every element in a list.
>
numbers = [0, 1, 2]transformed_data = []for n in numbers:transformed_data.append(n + 10)transformed_dataResult:
[10, 11, 12]
The example below uses a "list comprehension" to get the same result as above, but with much less code.
>
numbers = [0, 1, 2]transformed_data = [n + 10 for n in numbers]transformed_dataResult:
[10, 11, 12]
The square brackets make this a list comprehension (as opposed to other kinds of comprehensions that we'll see later). List comprehensions always result in a list. However, a comprehension can iterate over any iterable as its data source, not just lists. For example, comprehensions can iterate over ranges.
>
[value * 2 for value in range(3)]Result:
>
[value + 10 for value in range(6)]Result:
[10, 11, 12, 13, 14, 15]
We can filter out elements by adding an
if some_conditionclause at the end. If the condition is true, that value is included. If it's false, the value is skipped over. (In the next examplevalue % 2is onlyTruefor even numbers.)>
[value + 10 for value in range(6) if value % 2 == 0]Result:
[10, 12, 14]
>
names = ["Amir", "Betty", "Cindy"]ends_in_y = [name for name in names if name.endswith("y")]ends_in_yResult:
['Betty', 'Cindy']
Comprehensions can iterate over multiple iterables, similar to when we nest multiple
forloops. Here are two nestedforloops looping overintegersandstrings, producing all possible pairings of the integers and strings.>
integers = [0, 1]strings = ["a", "b"]- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
pairs = []for integer in integers:for string in strings:pairs.append((integer, string))pairsResult:
Now here's the comprehension version. Note the nice symmetry with the loop syntax: the
for integer in integersandfor string in stringsare the same in the loop and comprehension versions.- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
pairs = [(integer, string)for integer in integersfor string in strings]pairsResult:
We can even collapse the comprehension into a single line, though that makes it harder to read in this case.
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
[(integer, string) for integer in integers for string in strings]Result:
The symmetry between
forloops and comprehensions extends to iteration order as well. With aforloop or a comprehension, we'll get different results if we iterate overstringsfirst, as opposed to iterating overnumbersfirst.- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
[(integer, string)for string in stringsfor integer in integers]Result:
We can also use comprehensions to build dictionaries. To do this, we wrap the comprehension in
{}instead of[]. We specify each key and value pair withkey: value.>
items = [("a", 1), ("b", 2)]{item[0]: item[1]for item in items}Result:
{'a': 1, 'b': 2}In that example, the
item[0]: item[1]part could be more clear.item[0]is the key, anditem[1]is the value. It would be better if the comprehension started with{key: value. We can use the unpacking syntax to achieve that.>
items = [("a", 1), ("b", 2)]{key: valuefor key, value in items}Result:
{'a': 1, 'b': 2}All other details of dictionary comprehensions match what we saw for list comprehensions. They can have multiple
fors and they can haveifs.Comprehensions are a relatively unique feature of Python. That makes them fun, but it also brings a danger: the novelty can lead us to overuse them.
We recommend using comprehensions, but watching for complex comprehensions that become unwieldy. Sometimes a loop is easier to read, even if it takes a few more lines. Readability is more important than line count!
Here's a code problem:
Use a list comprehension to write a
double_numbersfunction. It should take a list, and return a new list with all of the numbers doubled. You can solve this with a one-line list comprehension!def double_numbers(numbers):return [2 * n for n in numbers]assert double_numbers([]) == []assert double_numbers([2, 4, 6]) == [4, 8, 12]assert double_numbers([-1, 3, 5]) == [-2, 6, 10]- Goal:
None
- Yours:
None