List Comprehensions in Python, Explained Step by Step
Once you are comfortable with for loops, you will start seeing a compact pattern in other people's code: square brackets with a for inside them. That is a list comprehension. It builds a new list from an existing one in a single line, and once you can read it, it is often clearer than the loop it replaces. The examples below build one up step by step. Each was run in Python 3 and shows its real output.
1. From loop to comprehension
The official tutorial says list comprehensions provide a concise way to create lists, typically by applying an operation to each item of another sequence, or by keeping only the items that meet a condition.
Here is a loop that adds 8 percent tax to a list of prices:
prices = [12.0, 7.5, 30.0, 4.25]
with_tax = []
for p in prices:
with_tax.append(round(p * 1.08, 2))
print(with_tax)
with_tax = [round(p * 1.08, 2) for p in prices]
print(with_tax)
[12.96, 8.1, 32.4, 4.59]
[12.96, 8.1, 32.4, 4.59]
Both produce the same list. Read the comprehension from the middle out:
for p in prices: go through each price.round(p * 1.08, 2): work out this value for each one.[ ... ]: collect the results in a new list.
The tutorial describes the shape as brackets containing an expression followed by a for clause, then zero or more for or if clauses.
2. Filtering with if
Put an if at the end to keep only some items:
prices = [12.0, 7.5, 30.0, 4.25]
cheap = [p for p in prices if p < 10]
print(cheap)
[7.5, 4.25]
Here the expression is just p, so each kept price goes into the new list unchanged.
3. Choosing between two values: if-else goes in front
Sometimes you want to keep every item but transform it one of two ways. That uses a different tool, the conditional expression, which the Python reference documents as x if condition else y. It goes at the front, in the expression position:
scores = [91, 58, 77, 64, 100]
labels = ["pass" if s >= 65 else "retry" for s in scores]
print(labels)
['pass', 'retry', 'pass', 'retry', 'pass']
The two forms are easy to mix up. A filter if at the end decides which items appear. A conditional if-else at the front decides what value each item becomes. Putting else at the end is a syntax error:
labels = [s for s in scores if s >= 65 else 0]
SyntaxError: invalid syntax
The exact wording of the error can vary between Python versions.
4. Cleaning data in one pass
Comprehensions combine well with string methods. Here, empty entries are dropped and the rest are converted to uppercase:
codes = ["ab-104", "", "cd-221", "ef-309", ""]
clean = [c.upper() for c in codes if c]
print(clean)
['AB-104', 'CD-221', 'EF-309']
if c works because an empty string counts as false in Python.
5. Two for clauses: flattening a list of lists
You can chain for clauses. The tutorial notes that their order is the same as it would be in nested loops: the first for is the outer loop.
teams = [["mina", "leo"], ["sam"], ["ana", "raj", "kim"]]
people = [name for team in teams for name in team]
print(people)
['mina', 'leo', 'sam', 'ana', 'raj', 'kim']
Read it as "for each team, for each name in that team, keep the name."
6. The same idea for dictionaries and sets
Curly braces give you a dictionary or set comprehension, which the tutorial also covers:
names = ["mina", "leo", "sam"]
lengths = {n: len(n) for n in names}
print(lengths)
first_letters = {n[0] for n in ["mina", "mark", "leo"]}
print(sorted(first_letters))
{'mina': 4, 'leo': 3, 'sam': 3}
['l', 'm']
key: value before the for makes a dictionary. A single expression inside braces makes a set, so the duplicate "m" appears only once.
7. One quiet advantage: no leftover variable
The tutorial points out that a regular for loop creates, or overwrites, its loop variable, and that variable still exists after the loop ends. A comprehension keeps its variable to itself:
for x in [1, 2, 3]:
pass
print(x)
squares = [n * n for n in [1, 2, 3]]
print(squares)
print(n)
3
[1, 4, 9]
NameError: name 'n' is not defined
After the loop, x is still 3. After the comprehension, n does not exist. That means a comprehension cannot accidentally overwrite a variable you were using elsewhere.
8. When to use a regular loop instead
Comprehensions are for building a list. Use a normal loop when:
- the body needs several steps, or would need a comment to explain;
- you are doing something for its effect, like printing or saving files, rather than collecting results;
- the comprehension stops fitting comfortably on one line.
A good test: if you have to read it twice, write the loop.
9. Key takeaways
[expression for item in items]builds a new list from an existing one.- An
ifat the end filters which items are kept. - An
if ... else ...at the front chooses each item's value;elseat the end is a syntax error. - Multiple
forclauses run in the same order as nested loops, which flattens lists of lists. - Prefer a regular loop when the logic is long or you are not building a list.