List Comprehensions

Build a list in one readable line

Beginner 10 min

In this lesson

A list comprehension is a short, readable way to build a new list from an existing one in a single line. It’s an extremely common Python pattern — once you can read them, you’ll see them everywhere.

Explain it like I’m 5

A comprehension is a sentence: ‘give me X for each item in this list’. It’s a compact way to say what would otherwise be a little loop that builds a new list.

From loop to comprehension

The long way to square a list is: make an empty list, loop, and append each squared value. A comprehension says the same thing in one line: [n * n for n in numbers]. Read it as ‘n * n for each n in numbers’. The expression on the left is what goes into the new list.

Example
# The long way
squares = []
for n in [1, 2, 3, 4]:
    squares.append(n * n)
print(squares)

# The comprehension — same result, one line
squares = [n * n for n in [1, 2, 3, 4]]
print(squares)
Output
[1, 4, 9, 16]
[1, 4, 9, 16]
Three lines of loop become one line.

Adding a filter

You can keep only some items by adding if: [n for n in numbers if n % 2 == 0] builds a list of just the even numbers. The structure is ‘expression for item in collection if condition’. The condition decides which items make it in; the expression decides what they become.

Example
numbers = [1, 2, 3, 4, 5, 6]
squares = [n * n for n in numbers]
evens = [n for n in numbers if n % 2 == 0]

print(squares)
print(evens)
Output
[1, 4, 9, 16, 25, 36]
[2, 4, 6]
Transforming and filtering in one line each.

Use a list comprehension to build a list of the lengths of each word, but only for words longer than 3 letters.

words = ["cat", "tiger", "ox", "panther", "ant"]
# lengths of words longer than 3 letters
result = []
print(result)

When to use one — and when not to

Comprehensions shine for simple transform-and-filter tasks: they’re shorter and signal intent clearly. But if the logic is complicated — multiple conditions, side effects, nested loops several levels deep — a plain for loop is more readable. Favour clarity over cleverness; a comprehension that’s hard to read has missed the point.

Dict and set comprehensions

The same idea works for dictionaries and sets. {name: len(name) for name in names} builds a dict mapping each name to its length. {n % 3 for n in numbers} builds a set. The curly braces and the key: value form are the only differences — the ‘for each’ thinking is identical.

Example
words = ["hi", "hello", "hey", "howdy"]
lengths = {w: len(w) for w in words}
print(lengths)
Output
{'hi': 2, 'hello': 5, 'hey': 3, 'howdy': 5}
A dict comprehension mapping words to their lengths.

Generator expressions: comprehensions without the list

Swap a comprehension’s square brackets for parentheses and you get a generator expression. Instead of building the whole list in memory, it produces items one at a time, on demand. That’s perfect when you only need to feed values into something like sum(), max(), or any(), or when the sequence is enormous.

sum(n * n for n in range(1000)) adds a thousand squares without ever storing a thousand-item list. (The { } versions you met earlier — set and dict comprehensions — build collections the same lazy-free way.)

Example
numbers = [1, 2, 3, 4, 5]

# A list comprehension builds the whole list:
squares = [n * n for n in numbers]
print(squares)

# A generator expression feeds sum() one value at a time:
total = sum(n * n for n in numbers)
print(total)
Output
[1, 4, 9, 16, 25]
55
Brackets build a list; parentheses make a lazy generator.

Common mistake: Cramming complex logic into a comprehension

Why it happens:

It’s tempting to keep adding conditions and nesting until the line is unreadable, prizing brevity over clarity.

How to fix it:

If a comprehension needs multiple conditions or nested loops to follow, rewrite it as a normal for loop. Readable beats clever.

Common mistake: Putting the filter in the wrong place

Why it happens:

A simple if that selects items goes at the end; an if/else that chooses the value goes before the for. Mixing these up is a common confusion.

How to fix it:

To filter: [x for x in items if cond]. To choose a value: [a if cond else b for x in items].

What does [n * 2 for n in [1, 2, 3]] produce?

Where does a filtering condition go in a comprehension?

Mini exercise (medium)

Given temps_c = [0, 20, 37, 100], use a list comprehension to build the same temperatures in Fahrenheit (c * 9 / 5 + 32).

Do it here. Finish the code below and press Run to try your answer right in the browser — no setup needed.

temps_c = [0, 20, 37, 100]
temps_f = []    # TODO: list comprehension  c * 9 / 5 + 32
print(temps_f)

What to learn next

You learned the comprehension syntax, how to transform and filter a list in a single line, when a comprehension reads better than a loop (and when it doesn’t), and dict comprehensions. You converted a list of Celsius temperatures to Fahrenheit in one expression.

Another everyday readability win is building text with values mixed in. f-strings covers embedding variables and expressions directly inside a string, formatting numbers and dates, and why f-strings beat the old concatenation approach. When you’re ready, continue to the next lesson.