- Python
- Tips
- Performance
Python List Comprehension: If Else and Examples
Python list comprehension explained: syntax, filtering with if, if else before for, nested loops, dict and set comprehensions, and loop speed.
A list comprehension in Python is a single expression that builds a new list by applying an expression to every item in an iterable, optionally keeping only the items that pass a condition. Its general form is [expression for item in iterable if condition], so [n * 2 for n in numbers if n % 2 == 0] doubles every even number. It replaces the "create an empty list, loop, append" pattern with one line that reads like a sentence.
Key takeaways
- The syntax is
[expression for item in iterable if condition], and theifclause is optional. - An
ifafter theforfilters items. To choose between two values, puta if condition else bbefore theforinstead. - You can chain
forclauses for nested data, but beyond two levels a normal loop is easier to read. - The same syntax builds dictionaries, sets and, with parentheses, memory-friendly generator expressions.
- A comprehension is usually somewhat faster than a loop that calls
append, but pick it for clarity first.
What is list comprehension in Python?
If you're coming from Java, C++ or PHP, you probably process arrays with for loops. Python has a more concise, idiomatic ("Pythonic") alternative.
The goal: from a list of numbers, build a new list containing only the even numbers, each multiplied by 2.
With a standard for loop
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result = []
for n in numbers:
if n % 2 == 0:
result.append(n * 2)
print(result)
# Output: [4, 8, 12, 16, 20]
This works and is readable, but it takes four lines and an explicit append call.
With a list comprehension
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result = [n * 2 for n in numbers if n % 2 == 0]
print(result)
# Output: [4, 8, 12, 16, 20]
The logic fits on one line and reads almost like English: "n times 2, for every n in numbers, if n is even." The Python tutorial on list comprehensions shows the same pattern.
How does list comprehension work in Python?
[expression for item in iterable if condition]
- Expression (
n * 2): the value placed in the new list. It can be arithmetic, a function call, a string method or even another comprehension. forclause (for n in numbers): the loop. The iterable can be a list, tuple,range, string, file object or anything else you can loop over.ifclause (if n % 2 == 0), optional: a filter. Items for which it is false are skipped.
Python evaluates the for and if clauses from left to right, exactly as if they were nested blocks written in the same order, and evaluates the expression once for each item that survives.
One difference from a loop: in Python 3 the loop variable belongs to the comprehension, so it doesn't overwrite a variable with the same name outside it.
x = "before"
squares = [x * x for x in range(4)]
print(squares)
print(x)
# Output:
# [0, 1, 4, 9]
# before
Example: cleaning a list of names
Strip whitespace and fix capitalisation in user input:
users = [" alice ", "bob", " CHARLIE "]
clean_users = [u.strip().title() for u in users]
print(clean_users)
# Output: ['Alice', 'Bob', 'Charlie']
List comprehension with if
An if placed after the for clause is a filter: it decides whether an item goes into the new list at all. The expression is left unchanged.
words = ["apple", "", "banana", "kiwi", ""]
non_empty = [w for w in words if w]
long_words = [w for w in words if len(w) > 4]
print(non_empty)
print(long_words)
# Output:
# ['apple', 'banana', 'kiwi']
# ['apple', 'banana']
You can write several if clauses in a row. An item is kept only when all of them are true, the same as joining the conditions with and:
multiples_of_15 = [n for n in range(50) if n % 3 == 0 if n % 5 == 0]
print(multiples_of_15)
# Output: [0, 15, 30, 45]
List comprehension with if else
To transform every item into one of two values, instead of dropping some, use a conditional expression (a if condition else b) before the for clause:
labels = ["even" if n % 2 == 0 else "odd" for n in range(5)]
print(labels)
# Output: ['even', 'odd', 'even', 'odd', 'even']
Why can't the if after for have an else?
The two positions are different parts of the grammar. The trailing if is a filter clause of the comprehension. Its only job is to keep or skip the current item, so there is no second value for an else to supply. Writing [n for n in nums if n > 0 else 0] raises a SyntaxError.
The if ... else before for is an ordinary conditional expression, the same one you can write anywhere, as in x = a if condition else b. It is the expression part, so it runs for every item and always produces a value. The rule of thumb:
- Filter (fewer items):
[x for x in items if condition] - Choose a value (same number of items):
[a if condition else b for x in items]
Combining if else with a filter
Both forms can appear in one comprehension. Here, missing scores are filtered out and the rest are labelled:
scores = [88, 42, 71, None, 95]
results = ["pass" if s >= 50 else "fail" for s in scores if s is not None]
print(results)
# Output: ['pass', 'fail', 'pass', 'pass']
Conditional expressions can be chained to act like elif, but more than one link quickly gets hard to read:
sizes = ["small" if n < 10 else "medium" if n < 100 else "large" for n in [5, 50, 500]]
print(sizes)
# Output: ['small', 'medium', 'large']
If you need more branches than that, move the logic into a small function and call it from the comprehension.
Nested list comprehensions
Flattening a matrix
To turn a 2D matrix (a list of lists) into a flat list, write the for clauses in the same order as nested loops, outer loop first:
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
flat = [num for row in matrix for num in row]
print(flat)
# Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
A comprehension inside a comprehension
When the expression is itself a comprehension, you get a list of lists. This one swaps rows and columns (transposes the matrix):
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
columns = [[row[i] for row in matrix] for i in range(3)]
print(columns)
# Output: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
The inner comprehension runs once for each value of i. Tip: avoid nesting more than two levels deep. If a comprehension no longer reads easily, a regular loop is the better choice.
Dictionary and set comprehensions
The same syntax builds dictionaries when you use curly braces and a key: value expression:
my_dict = {'a': 1, 'b': 2, 'c': 3}
swapped = {value: key for key, value in my_dict.items()}
print(swapped)
# Output: {1: 'a', 2: 'b', 3: 'c'}
names = ["Ada", "Grace", "Linus"]
lengths = {name: len(name) for name in names}
print(lengths)
# Output: {'Ada': 3, 'Grace': 5, 'Linus': 5}
Curly braces without a colon build a set, which removes duplicates:
squares = {n * n for n in [1, -1, 2, -2]}
print(squares)
# Output: {1, 4}
Generator expressions
A list comprehension builds the entire list in memory at once. A generator expression, written with parentheses instead of square brackets, produces items one at a time as they're consumed. When it is the only argument to a function, the extra parentheses can be dropped:
total = sum(x * 2 for x in range(1_000_000))
print(total)
# Output: 999999000000
Only one value exists at a time, so memory use stays small no matter how large the range is. The trade-off is that a generator can only be consumed once:
squares = (n * n for n in range(4))
print(list(squares))
print(list(squares))
# Output:
# [0, 1, 4, 9]
# []
Is list comprehension faster than a for loop?
Usually it is somewhat faster than an equivalent loop that calls append. In the loop version, every iteration looks up the result.append attribute and then calls it as a method. A list comprehension compiles to a dedicated bytecode instruction, LIST_APPEND, which adds each item to the list being built directly, with no attribute lookup or method call.
Python 3.12 removed another cost: PEP 709 inlines list, dictionary and set comprehensions instead of creating a single-use function object each time one runs, and the release notes say this speeds up a comprehension "by up to two times".
In practice the gain is moderate rather than dramatic. When we timed the even-number example above on a 10,000-item list with python -m timeit, the comprehension came out ahead on every run, by a clear but modest margin. Both versions still run as Python bytecode, and if the loop body does real work, such as calling a function or parsing a string, that work dominates and the difference shrinks. Choose a comprehension because it's clearer, and measure with the timeit module when speed really matters.
When not to use a list comprehension
A comprehension is for building a list. Reach for a regular loop when:
- You only want side effects.
[print(name) for name in names]works, but it builds and throws away a list ofNonevalues. A plainforloop says what you mean. - The logic needs statements. Comprehensions can't contain
try/except,with, assignments to several variables or multiple steps. - There are more than two nested loops or conditions. Readability drops fast.
- You don't need the list. For a total or a yes/no answer, pass a generator expression to
sum(),any()orall()instead.
names = ["Ada", "Grace", "Linus"]
# Avoid: builds a throwaway list of None values
# [print(name) for name in names]
# Prefer a plain loop for side effects
for name in names:
print(name)
# Prefer a generator expression when you only need an answer
print(any(len(name) > 4 for name in names))
# Output:
# Ada
# Grace
# Linus
# True
Try it yourself
Run these examples in the WebFiddle Python sandbox. It runs Python in your browser through Pyodide, so you can edit a comprehension, add an if or else and see the result without installing anything. If you're choosing a tool for learning Python, see our comparison of the best online Python compilers.
Frequently asked questions
What is list comprehension in Python?
A list comprehension is a compact way to create a new list from any iterable in one expression. You write the value to produce, a for clause that loops over the data and an optional if clause that filters it, all inside square brackets. It replaces the pattern of creating an empty list and appending to it inside a loop.
Can you use if else in a list comprehension?
Yes, but the position matters. An if on its own goes after the for clause and filters items out. An if with an else is a conditional expression, so it goes before the for clause and chooses a value for every item. Putting an else after the for clause is a syntax error. Both forms can be combined.
Is list comprehension faster than a for loop?
Usually it is somewhat faster than an equivalent loop that calls append, because it adds items with a dedicated bytecode instruction instead of looking up and calling a method on each iteration. Python 3.12 also inlines comprehensions. The gain is moderate, and it shrinks when the loop body does heavy work, so measure with timeit.
How does list comprehension work in Python?
Python runs the for and if clauses from left to right, as if they were nested blocks in a loop. For each item that passes every if clause, it evaluates the expression at the front and adds the result to a new list. In Python 3 the loop variable stays inside the comprehension and does not leak out.
What is the difference between a list comprehension and a generator expression?
A list comprehension uses square brackets and builds the complete list in memory immediately. A generator expression uses parentheses and produces values lazily, one at a time, as they're requested. Generators use far less memory for large inputs, but they can only be iterated once and don't support indexing or taking their length.
WebFiddle