List Comprehensions
Build a new list from an iterable, add a filter, and explain the output before running it.
Video lesson: List Comprehensions
The preview is stored on this site. YouTube loads only when you press Play. Watch on YouTube
Jump to a chapter
Read the video transcript
Select a timestamp to watch that moment on YouTube.
- 00:00
A list comprehension can replace a small loop with one readable expression, but a short expression can also hide a wrong condition. We want to double only the even numbers in this list: one, two, three, and four. Before I run anything, predict the output. If our filter is correct, the input two becomes four and the input four becomes eight. One and three should disappear. The full lesson on PythonLessonLab has a browser console where you can change the list and check your prediction. For the video, I will run a mistaken version first. It is useful because it does not crash. It prints a believable list, and that is exactly the kind of bug that can slip past us if we only check that the program ran.
- 00:45
Keep the expected answer, four and eight, in mind as we inspect the first run. A comprehension does not mutate the source list in this example. It constructs a new list, so you can compare the old and new values after the run. This matters when you want to keep the original data for another calculation. The terminal prints two and six. Those are one and three doubled, so our program selected the odd inputs instead of the even inputs. Let us read the comprehension in pieces. The expression on the left, n times two, tells Python what to put in the new list. The for clause visits each n in numbers.
- 01:25
The last if clause decides whether the current n is kept at all. This is a filter, not an instruction to change n. The mistake is in that filter. The expression n modulo two returns the remainder after dividing n by two. For one the remainder is one, for two it is zero, for three it is one, and for four it is zero. Python treats a nonzero number as true and zero as false in a condition. The written filter therefore keeps one and three. Nothing about the multiplication itself was wrong. The list comprehension did exactly what we asked, but we asked the wrong question. Notice that the two printed numbers are doubled odd inputs, not an exception.
- 02:08
A wrong result can be harder to catch than a traceback because the program exits successfully. A small prediction written before running is a practical test oracle. Printing the condition values gives us evidence instead of a guess. The remainders are one, zero, one, zero. In an if condition, the two ones pass, so the comprehension collects the doubled values from positions one and three. A normal loop can make the same sequence explicit: create an empty result list, visit each number, check the condition, and append the doubled value only when the condition passes. The comprehension puts those same parts in a tighter order: output expression, for clause, optional filter.
- 02:53
It creates a new list and leaves numbers unchanged. That makes it a good fit for a simple transformation like this. If you need several statements or complex error handling for every item, keep the ordinary loop. Readability matters more than using the shortest syntax. Here we can repair the filter without changing the rest of the expression. Make the check explicit while learning: write n remainder two equals equals zero. It takes a few more characters, but a reader can see the even-number rule immediately. Shorter code is not automatically clearer code. The corrected condition says explicitly that the remainder must equal zero.
- 03:34
Now two and four pass, and the terminal prints four and eight. That matches the prediction from the opening. Notice that the condition is at the end: if n modulo two equals zero. A trailing if filters the source items. If you put an if between the expression and the for clause, you are writing a conditional expression, which has a different shape and requires an else branch. Many confusing comprehension errors come from mixing those two forms. Build confidence by writing the simple loop first, confirming its output, and then replacing it with a comprehension that reads clearly. You can also test a second input.
- 04:14
A good test has both passing and failing values, so an accidentally inverted filter cannot look right by chance. The expression n times two runs only for inputs that pass the filter. With the corrected condition, one and three are skipped, while two becomes four and four becomes eight. Print the source list afterward to confirm it stayed intact. With an empty source list, there is nothing to test or double. The result is an empty list, not an error and not a list containing zero. That boundary check matters because functions often receive empty collections in real programs. On the lesson page, the practical task asks you to write even_squares.
- 04:56
It should return the squares of the even inputs in their original order. For one through six, the expected result is four, sixteen, thirty-six. Try the task before copying a solution. Check a list with negative two, negative one, zero, and three as well; negative two and zero are even, so their squares should be four and zero. The site checks those cases and whether the original list remains unchanged. Then answer the three-question quiz to complete the lesson. For your own extension, clean a list of names with strip and lower, or filter out empty strings. The same comprehension pattern works whenever one clear transformation and one clear filter explain the result.
- 05:40
As a second variation, change the input to include zero and a negative even number. Predict the output and then run it. If your expression or filter grows into several decisions, use a normal loop so each step remains easy to inspect.
Understand the concept
A list comprehension creates a new list by describing what to collect and where each value comes from. The compact form [expression for item in source] has the same result as a loop that appends one expression result per item. Read it from the middle first: for each item in source, evaluate the expression at the left and place it in the resulting list.
You can add if condition at the end to keep only source items that pass a test. The condition is evaluated before the expression is added. In [n * 2 for n in numbers if n % 2 == 0], only even values are doubled. The if clause does not change n; it decides whether that n contributes an output item.
A comprehension is useful when the output is one clear transformation of a collection. A normal loop is often easier to read when you need several statements, error handling, or side effects for each item. Do not make a comprehension longer just to avoid writing a loop. First get the loop right, then shorten it if the intent remains obvious.
Always test a small input and a boundary case. An empty input produces an empty list. A mistaken filter such as if n % 2 keeps odd numbers because the remainder is 1 for odd numbers and 0 for even numbers; Python treats 1 as true and 0 as false. Write the comparison == 0 when you mean even.
- [expression for item in source] makes a new list
- An optional if clause filters source items
- A clear loop can be better than a crowded comprehension
See it step by step
Read the code, predict the output, then compare it with the result.
01. Replace an append loop
numbers = [1, 2, 3]
doubled = [number * 2 for number in numbers]
print(doubled)[2, 4, 6]The left expression runs once for each number. The output is a new list; numbers still contains 1, 2, and 3.
02. Filter before collecting
numbers = [1, 2, 3, 4]
doubled_evens = [n * 2 for n in numbers if n % 2 == 0]
print(doubled_evens)[4, 8]Only 2 and 4 pass the even test. The expression doubles those two values.
03. Clean text values
names = [" Ada ", " BO "]
cleaned = [name.strip().lower() for name in names]
print(cleaned)['ada', 'bo']Each source string is stripped and lowercased; the original strings are not modified.
A closer look
Follow the reasoning, inspect each result, then try the suggested changes in the console below.
Read the loop before shortening it
A comprehension is easier to understand when you can first explain the loop it replaces. Start with an empty result list. For each source item, calculate the output value and append it. The comprehension moves that output expression to the left of the for clause, but the meaning is the same. This is not a mutation of the source list: both forms build another list. That distinction matters when other code still uses the original input after the calculation.
Read [number * 2 for number in numbers] as an instruction: visit every number, multiply it by two, and collect the products. The order of the result follows the order of the input. If numbers is empty, the loop body never runs and the new list is empty. Before replacing a loop with a comprehension, ask whether the entire job can be said clearly in one sentence. Several dependent actions or a complex branching path often deserve an ordinary loop.
numbers = [2, 3, 4]
with_loop = []
for number in numbers:
with_loop.append(number * 2)
with_comprehension = [number * 2 for number in numbers]
print(with_loop)
print(with_comprehension)
print(numbers)[4, 6, 8]
[4, 6, 8]
[2, 3, 4]- The loop appends one doubled number at each iteration.
- The comprehension collects the same three values in the same order.
- Change numbers to [] and predict all three printed lists.
A filter needs the right truth value
The optional if clause appears after the for clause and decides which source items contribute to the output. It is a filter, not a replacement value. The source item is evaluated by the condition first; only when the condition is true does Python evaluate and collect the expression on the left. To keep even values, test whether the remainder after division by two equals zero. Write the comparison explicitly because it communicates the intent to a reader as well as to Python.
A common plausible-looking error is if n % 2. For an odd n, the remainder is one, and one is truthy. For an even n, the remainder is zero, and zero is falsy. The code runs without an exception but keeps exactly the opposite parity from the intended one. A small test input containing both odd and even values exposes the error immediately. Predict both outputs before running the example.
numbers = [1, 2, 3, 4]
print([n % 2 for n in numbers])
print([n * 2 for n in numbers if n % 2])
print([n * 2 for n in numbers if n % 2 == 0])[1, 0, 1, 0]
[2, 6]
[4, 8]- The remainder list exposes the condition value for every source item.
- Nonzero remainders admit odd values in the incorrect version.
- The explicit comparison with zero admits only even values.
Keep the result and edge cases visible
A comprehension can transform and filter in one readable pass. Here, strip surrounding whitespace from each name, keep only nonempty results, and lowercase the kept strings. The cleaned name appears in both the expression and the condition. For a tiny list this repeated operation is harmless, but a costly computation should not be repeated merely to force everything into one line. A loop with a named intermediate value would be clearer in that case.
Test an input with blank strings as well as ordinary names. The empty result is meaningful: there were no names to keep. If downstream code assumes at least one item and indexes result[0], the error belongs to that assumption, not to the comprehension. Before relying on a list result, check what an empty input or an all-filtered input should mean for your program. The checked task uses a function so the same rule can be tested with several lists.
names = [" Ada ", " ", " BO "]
cleaned = [name.strip().lower() for name in names if name.strip()]
print(cleaned)
print([name.strip().lower() for name in [] if name.strip()])['ada', 'bo']
[]- Whitespace-only text becomes empty after strip and fails the filter.
- The kept strings are lowercased in their original order.
- Try replacing names with a list containing only blanks and predict the result.
Try it in Python
Edit the example and run it. Python starts in your browser the first time you click Run.
Python console
Ready to runNeed input()? Add one value per line
Your output appears here.
Need a hint?
Start with [value * value for value in values]. Add if value % 2 == 0 after the for clause. Return the new list rather than printing it inside the function.
Complete the task and select Check task to verify your code.
Quick quiz
Three questions. You can change your answers and try again.
Typical mistakes
Everyone meets these errors. See what causes them and how to fix them.
Filtering odd values by accident
[n * 2 for n in numbers if n % 2][n * 2 for n in numbers if n % 2 == 0]What happens: The result contains doubled odd values, such as [2, 6] for [1, 2, 3, 4].
The remainder is 1 for odd numbers, which is truthy. Compare explicitly with zero for even values.
Putting the filter before the loop
[n * 2 if n % 2 == 0 for n in numbers][n * 2 for n in numbers if n % 2 == 0]What happens: SyntaxError: expected else after the conditional expression.
A trailing if filters items. An if before for is a different expression form and needs an else branch.