names = ['Ama', 'Ben', 'Chen', 'Dina', 'Eli']
hours = [2, 4, 5, 1, 3]
scores = [55, 65, 80, 40, 60]
passes = []
for s in scores:
if s >= 50:
passes.append(s)
print(passes)[55, 65, 80, 60]
Before this lesson
P01.6 Lists, tuples, dictionaries and sets P01.9 Objects and classes
After this lesson you can
In review. The maths and code on this page are checked by automated tests on every change, but an independent reader has not signed it off yet. Spot a mistake or a confusing step? Tell us.
You have written these four lines many times: make an empty list, loop over the scores, test each one, append the ones that pass. The sentence they stand for is short: “the scores that are at least 50”. Can the code be as short as the sentence, and still be read from left to right?
Most loops that build a list have the same shape. An empty list is made, a loop walks over another list, an if decides which items to keep, and append adds something made from each kept item. Only three things change from one such loop to the next: what is appended, what is looped over, and the test.
A comprehension writes those three things, and nothing else, inside one pair of brackets.
One loop, one expression. Each numbered part of the comprehension is one line of the loop, read in a new order: what to keep first, then where it comes from, then the test.
The parts keep their order except for one. The thing appended, which comes last in the loop, moves to the front of the comprehension. So the line reads almost like the sentence: “s, for each s in scores, if s >= 50”.
The study table gives the running data, as in every lesson of this course.
[55, 65, 80, 60]
That is the loop. Now build the comprehension one part at a time.
Step 1. Output expression and for clause. The smallest comprehension has two parts: an expression, then a for clause. [s for s in scores] makes a new list holding every score: a copy.
Step 2. Add an if clause. An if at the end keeps only the items for which the test is True. [s for s in scores if s >= 50] drops 40, the one score below the pass mark.
Step 3. Change the output expression. The expression at the front can be any expression that uses the name. [band_of(s) for s in scores] gives the band of each score, with the function of P01.6.3.
Three steps. The for clause alone copies; an if clause filters; a new output expression transforms each item.
[55, 65, 80, 40, 60]
[55, 65, 80, 60]
['pass', 'pass', 'distinction', 'fail', 'pass']
The output expression can do arithmetic too. The running function predict of this course turns every number of hours into a predicted score.
A list comprehension is an expression in square brackets: an output expression, then a for clause, then zero or more further for or if clauses.
It makes a new list. It means exactly this loop, run on the spot:
The Python Tutorial (section 5.1.3) defines it in the same words: “brackets containing an expression followed by a for clause, then zero or more for or if clauses”. Three rules follow from the loop above.
for is new and belongs to the comprehension. After the line has run, the name s of [s for s in scores] is not left behind, and a name s outside the comprehension, if there is one, keeps its old value.Dictionaries and sets. The same idea works in curly brackets. A dictionary comprehension has a key and a value with a colon between them; a set comprehension has one expression.
A dictionary comprehension makes key-value pairs; a set comprehension makes a set, so repeats collapse to one.
The dictionary maps each name to a score, with zip from P01.6.2 handing over the pairs. The set holds each band once: five bands go in and three come out, because a set keeps one of each (P01.6.3). A set has no positions, so the order in which Python prints it is not something to rely on.
Work out [s for s in scores if s >= 50] by hand, then the mean of the passes. The trace table has one row for each item of scores.
The trace of the comprehension. Only the row whose test is False leaves the list as it was.
s is 55. The test \({55 \ge 50}\) is True, so 55 is added.[55, 65, 80].[55, 65, 80, 60].Four students passed. Their scores add up to \({55 + 65 + 80 + 60} = 260\), so the mean of the passes is \({260 / 4} = 65.0\), the number this course has met before.
The worked example, then the mean of the passes and the two curly-bracket forms.
[55, 65, 80, 60] 4 65.0
{'Ama': 55, 'Ben': 65, 'Chen': 80, 'Dina': 40, 'Eli': 60}
80
3 ['distinction', 'fail', 'pass']
The set is printed through sorted, which turns it into a list in alphabetical order, so that the output is the same on every run.
A comprehension can also build the numbers machine learning cares about. The errors of predict are the scores minus the predictions, and their mean square is the mean squared error of the course, 8.
[4, -4, 2, -2, 0]
8.0
The loop variable of a for statement is left behind with its last value, while the name inside a comprehension is not. That difference rarely matters, but it is one reason comprehensions are tidy.
This module’s interactive, the lazy and eager pipeline, lives in P01.10.3. Its eager mode is made of the list comprehensions of this lesson: each one builds its whole list before the next one starts. Count how many items are held in lists by the end; lesson P01.10.3 shows how to hold far fewer.
Wrong beside right. A comprehension used only for what it does along the way builds a list of None for nothing; a loop says what is meant.
“A comprehension is just a shorter loop, so I can use it for anything a loop does.”
A comprehension is for making a list. [print(s) for s in scores] prints the five scores, but it also builds a list of five None values, because print returns None, and then throws it away. When the point of a loop is what it does along the way (printing, writing to a file, changing another object), write a plain for loop.
“If two clauses are good, three are better.”
[s for row in table for s in row if s >= 50] is legal, and it takes the passing scores out of a list of lists. Few readers can follow it at a glance. With more than two clauses, or with a test that needs elif, a plain loop with good names is clearer, and clear code is code you can debug.
“The comprehension changed my list.”
It never does. [s for s in scores if s >= 50] makes a new list and leaves scores with all five items. To keep the result, give it a name.
1. What are the three parts of [s for s in scores if s >= 50]?
The output expression s, the for clause for s in scores, and the if clause if s >= 50.
2. Write the loop that [predict(h) for h in hours] stands for.
result = [], then for h in hours: with the body result.append(predict(h)).
3. How many items does [s for s in scores if s >= 50] have, and why?
Four: one for each score that passes the test. Only 40 fails it.
4. What is the difference between {band_of(s) for s in scores} and [band_of(s) for s in scores]?
The first is a set, with each band once (three items, no positions); the second is a list with one band per score (five items, in order).
5. Name two cases in which a plain loop is clearer than a comprehension.
When the loop is there for its side effects, such as printing; and when there are more than two clauses.
1. ★ Write a comprehension for the names of the students who studied at least 3 hours, using zip(names, hours). Work out its value by hand.
[name for name, h in zip(names, hours) if h >= 3]. The pairs are (Ama, 2), (Ben, 4), (Chen, 5), (Dina, 1) and (Eli, 3). The hours 4, 5 and 3 pass, so the value is ['Ben', 'Chen', 'Eli'].
2. ★★ Write a dictionary comprehension that maps each name to its band, and say how many keys map to 'pass'.
{name: band_of(score) for name, score in zip(names, scores)} gives Ama, Ben and Eli 'pass', Chen 'distinction' and Dina 'fail'. Three keys map to 'pass', as in the tally of P01.3.1.
3. ★★★ Rewrite this loop as one comprehension, then check that both give the same list by hand.
gaps = [s - predict(h) for h, s in zip(hours, scores) if s >= 50]. The output expression is the thing appended, the for clause is the loop header, and the if clause is the test. By hand: the errors are 4, -4, 2, -2 and 0, and Dina’s row, with score 40, fails the test. So both give [4, -4, 2, 0].
A comprehension is the loop-and-append pattern written as one expression.
Loop and comprehension, part by part.
[expression for name in iterable if condition], a new list.{key: value for name in iterable}; set: {expression for name in iterable}.Sources. Each was opened and checked against this lesson on 12 November 2026.
for clause, then zero or more for or if clauses” and gives the equivalent loop; section 5.4 shows set comprehensions and section 5.5 dictionary comprehensions.for and if clauses.Next. P01.10.2 Iterables and iterators opens up the for clause and shows what a loop really asks of the list it walks over.
This lesson unlocks
P01.10.2 Iterables and iterators