List Comprehensions
In the For Loops lesson you built new lists by starting with an empty list and appending inside a loop. That pattern is so common that Python has a shortcut for it: the list comprehension. It builds a new list from another collection in a single, readable line.
From loop to comprehension
Here's the loop way of squaring some numbers:
numbers = [1, 2, 3, 4, 5]
squares = []
for n in numbers:
squares.append(n ** 2)
print(squares)And here's the same thing as a list comprehension:
numbers = [1, 2, 3, 4, 5] squares = [n ** 2 for n in numbers] print(squares)
Read it as: "n ** 2 for each n in numbers". The general shape is:
new_list = [expression for item in collection]
Each part of the loop has a place in the comprehension:
| In the loop | In the comprehension |
|---|---|
squares = [] |
the square brackets [ ] around everything |
for n in numbers: |
for n in numbers (no colon) |
squares.append(n ** 2) |
n ** 2, written first |
The expression comes first because it's what ends up in the new list. The comprehension always builds a new list; numbers is left unchanged.
More examples
The expression can be anything: a calculation, a method call or a function call.
names = ["ada", "grace", "alan"] print([name.capitalize() for name in names]) print([len(name) for name in names]) print([n * 10 for n in range(5)]) # add 20% tax to each price prices = [4.99, 12.5, 3.25] print([round(p * 1.2, 2) for p in prices])
The new list always has one item for each item in the original, in the same order. Three names in, three results out.
Filtering with if
Add if at the end to keep only some items:
new_list = [expression for item in collection if condition]
numbers = [12, 7, 3, 18, 25, 4, 9] evens = [n for n in numbers if n % 2 == 0] print(evens) big = [n for n in numbers if n > 10] print(big) words = ["apple", "kiwi", "banana", "fig", "cherry"] print([w for w in words if len(w) > 4])
For each item, Python checks the condition first. If it's True, the expression is added to the new list; if not, the item is skipped. So for evens: 12 passes (12 % 2 == 0), 7 is skipped, 3 is skipped, 18 passes, and so on, giving [12, 18, 4]. With a filter, the new list can be shorter than the original, or even empty.
[n for n in numbers if ...] keeps the items unchanged (the expression is just n). You can filter and transform at once, as in [n * 10 for n in numbers if n > 10].
Here's the example from the start of this tutorial: word lengths, skipping the word "the":
sentence = "the quick brown fox jumps over the lazy dog" words = sentence.split() word_lengths = [len(word) for word in words if word != "the"] print(words) print(word_lengths)
Choosing a value with if-else
To transform each item one of two ways, rather than filter, put a conditional expression at the front:
scores = [45, 82, 67, 91, 38] results = ["pass" if s >= 50 else "fail" for s in scores] print(results) # replace negatives with 0 numbers = [3, -1, 4, -5, 9] print([n if n > 0 else 0 for n in numbers])
This uses the one-line value_if_true if condition else value_if_false from the If / Elif / Else lesson as the expression. Every item produces a value, so the new list is always the same length as the original. The else is required here: without it, Python wouldn't know what to put in the list for the other items.
Remember:
ifat the end filters items out.if ... elseat the front chooses what each item becomes.
| You want | Write | Result for [3, -1, 4] |
|---|---|---|
| drop the negatives | [n for n in nums if n > 0] |
[3, 4] |
| replace the negatives | [n if n > 0 else 0 for n in nums] |
[3, 0, 4] |
Mixing them up is a SyntaxError: [n for n in nums if n > 0 else 0] isn't allowed, because a filter at the end can't have an else.
Dictionary comprehensions
Use curly braces and a key: value expression to build a dictionary:
names = ["ada", "grace", "alan"]
name_lengths = {name: len(name) for name in names}
print(name_lengths)
prices = {"coffee": 3.0, "tea": 2.5, "cake": 4.0}
sale = {item: round(price * 0.8, 2) for item, price in prices.items()}
print(sale)
cheap = {item: price for item, price in prices.items() if price < 3.5}
print(cheap)- The part before the colon becomes the key, and the part after it the value:
name: len(name)gives'ada': 3. for item, price in prices.items()unpacks each(key, value)pair, just like in aforloop.- An
ifat the end filters, exactly as in a list comprehension. - Keys must be unique. If two items produce the same key, the last one wins.
Going deeper: Set comprehensions optional
Curly braces with a single expression make a set, so duplicates disappear:
words = ["Apple", "avocado", "Banana", "blueberry", "cherry"]
first_letters = {w[0].lower() for w in words}
print(sorted(first_letters))Going deeper: More than one for optional
A comprehension can have more than one for, read left to right like nested loops:
pairs = [(x, y) for x in range(1, 4) for y in ["a", "b"]] print(pairs) grid = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] flat = [n for row in grid for n in row] print(flat)
When not to use one
Comprehensions are great for short, clear transformations. If yours gets long, has several conditions or needs print() calls, a regular for loop is easier to read. Readability matters more than saving lines.
Exercises
Exercise 1: Celsius to Fahrenheit
Convert every temperature to Fahrenheit (c * 9 / 5 + 32) with a list comprehension. It should print [32.0, 50.0, 68.0, 86.0, 104.0].
celsius = [0, 10, 20, 30, 40]
The shape is [expression for c in celsius].
The expression is the formula itself: c * 9 / 5 + 32.
Exercise 2: Vowel-starting words
Make a list of the words that start with a vowel. It should print ['apple', 'orange', 'umbrella', 'egg'].
words = ["apple", "banana", "orange", "grape", "umbrella", "egg", "kiwi"]
Add a condition at the end: [w for w in words if ...].
w[0] in "aeiou" checks whether the first letter is a vowel.
Exercise 3: Rewrite the loop
Rewrite this loop as a single list comprehension that produces the same result.
numbers = range(1, 21)
result = []
for n in numbers:
if n % 3 == 0:
result.append(n * n)
print(result)What you append goes first, then the for part, then the if part at the end.
Exercise 4: Grade book
Use a dictionary comprehension to map each student to "pass" (score 50 or more) or "fail". It should print {'Mia': 'pass', 'Leo': 'fail', 'Ava': 'pass'}.
scores = {"Mia": 78, "Leo": 42, "Ava": 91}
A dictionary comprehension looks like {name: ... for name, score in scores.items()}.
The value is a conditional expression: "pass" if score >= 50 else "fail".
Summary
[expr for item in collection]builds a new list in one line.- Add
if conditionat the end to filter items. - Put
a if condition else bat the front to choose each item's value. {key: value for ...}builds a dictionary the same way.- Use a regular loop when a comprehension stops being easy to read.
Know something worth teaching? Write your own tutorial with runnable examples and share it.