List comprehensions

Introduction

Many loops follow the same pattern: start with an empty list, loop, and append something each time. A list comprehension writes that whole pattern in one readable line.

So much programming is "start with an empty list, loop, and add something" that Python has a special form for it. Used well, a comprehension says what you want in one clear line.

How it works

From a loop to one line

squares = []
for n in range(1, 6):
    squares.append(n * n)
print(squares)

same = [k * k for k in range(1, 6)]
print(same)
Open in compiler

Both halves build [1, 4, 9, 16, 25]. The first uses a loop and append; the second says the same thing in one line:

[k * k for k in range(1, 6)] reads as "k times k, for each k in 1 to 5".

Step through and compare. The loop takes several steps per item on lines 2 and 3. The comprehension stays on line 6 while it works through the items, and the finished list appears in same only once it is complete.

Dictionary comprehensions

words = ["code", "base", "python"]
lengths = {w: len(w) for w in words}
print(lengths)
Open in compiler

The same idea with curly brackets and a key: value pair builds a dictionary: each word maps to its length.

FormBuilds
[expr for x in items]a list
[expr for x in items if test]a filtered list
{key: value for x in items}a dictionary
{expr for x in items}a set

Syntax

[n * n for n in nums]
[n for n in nums if n > 0]
{w: len(w) for w in words}
{x % 3 for x in nums}

Example

marks = [72, 35, 90, 48, 61]
passed = [m for m in marks if m >= 40]
print(passed)
Open in compiler

Adding if at the end keeps only the items that pass the test. Here, marks of 40 or more. Stepping shows line 2 once for each of the five marks; then passed appears holding [72, 90, 48, 61].

Line by line

  1. marks holds five values.
  2. m for m in marks goes through each mark.
  3. if m >= 40 keeps only the marks that pass the test.
  4. The first m says what to put in the new list, which is the mark itself.
  5. print shows the new list, while marks is unchanged.

Expected result

[72, 90, 48, 61]

In the real world

Data work is full of comprehensions: selecting rows, cleaning values, building lookup tables. They are also common in interviews, as a quick way of showing fluency.

Common mistakes

  • Squeezing too much into one line. If a comprehension needs nested loops and several conditions, a normal loop is clearer.
  • Using a comprehension only for its side effects, such as [print(x) for x in items]. Use a for loop when you are not building a list.
  • Expecting the loop variable to exist afterwards. A comprehension's variable stays inside it.

Best practices

  • Keep comprehensions to one simple idea.
  • Name the loop variable clearly.
  • Use a generator expression when you only need to add up or search.

Summary

A comprehension builds a list, dictionary or set from a loop in one line, and an if at the end filters. For complicated logic, a normal loop is easier to read.

Practice

Read a line of words and print a list of the words written in capital letters, using one comprehension and upper().

Quick check

1. What does [n * 2 for n in range(3)] give?
2. What does [w for w in ['a', 'bb', 'ccc'] if len(w) > 1] give?
3. Which builds a dictionary?

Key takeaways

  • Read a comprehension from the left: what to make, then where it comes from.
  • Put the if at the end to filter.
  • Use a normal loop when a comprehension gets hard to read.

Practice problems for this lesson

My notes

Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.