Python List comprehensions
By Flavio Copes
Learn Python list comprehension syntax, including transformations, filters, conditional expressions, and when a loop or generator expression is clearer.
A list comprehension creates a new list from an iterable.
The basic syntax is:
[expression for item in iterable]
For example, you can square every number in a list:
numbers = [1, 2, 3, 4, 5]
numbers_squared = [number**2 for number in numbers]
# [1, 4, 9, 16, 25]
This is equivalent to:
numbers_squared = []
for number in numbers:
numbers_squared.append(number**2)
It also replaces many simple uses of map():
numbers_squared = list(map(lambda number: number**2, numbers))
The comprehension is usually easier to read. The pattern of “build a new list by transforming each item” is so common in Python that the language gave it dedicated syntax.
The loop variable does not leak, either. After the comprehension runs, number does not exist in the surrounding scope.
See the official Python list comprehensions tutorial and language reference for the complete rules.
Filter values
Add an if clause after the loop to keep matching values:
numbers = [1, 2, 3, 4, 5]
even_numbers = [number for number in numbers if number % 2 == 0]
# [2, 4]
The expression still decides what goes into the new list:
even_numbers_squared = [
number**2
for number in numbers
if number % 2 == 0
]
# [4, 16]
Use a conditional expression
Put a conditional expression before for when every input should produce a value:
labels = [
'even' if number % 2 == 0 else 'odd'
for number in numbers
]
# ['odd', 'even', 'odd', 'even', 'odd']
Notice the difference:
ifafterforfilters values outif...elsebeforefortransforms every value
What about nested loops?
A comprehension can have more than one for clause. They read left to right, exactly like nested loops:
matrix = [[1, 2], [3, 4], [5, 6]]
flat = [number for row in matrix for number in row]
# [1, 2, 3, 4, 5, 6]
The equivalent loop makes the order clear:
flat = []
for row in matrix:
for number in row:
flat.append(number)
The pitfall is writing the clauses in the wrong order. [number for number in row for row in matrix] raises a NameError, because row is used before it is defined. Write the for clauses in the same order you would write the nested loops, outer loop first.
Keep comprehensions readable
List comprehensions are great for a small transformation or filter.
Use a regular loop when the operation needs side effects, several steps, or complicated conditions. Clear code is more important than fitting everything on one line.
A list comprehension creates the whole list immediately. Use a generator expression when you want to produce values lazily:
squares = (number**2 for number in range(1_000_000))Related posts about python: