Many loops follow the same pattern: start with an empty list, loop over some values, change or filter each one, and append the result. Python has a shorter way to write exactly that pattern, called a list comprehension. It turns four lines into one, and once you're used to it, it's also easier to read.
Comprehensions work for dictionaries and sets too. Alongside them, Python lets you write tiny unnamed functions called lambdas, which are handy when another function, such as sorted(), needs to know how to compare items.
These tools are everywhere in real Python code, from data analysis to web development. In this lesson you'll learn to read and write comprehensions confidently, and you'll also learn when not to use them, because a clear loop is better than a clever one-liner nobody can follow.
From loop to comprehension
Here's a loop that squares every number:
squares = []
for n in range(1, 6):
squares.append(n * n)And here's the same thing as a list comprehension:
squares = [n * n for n in range(1, 6)] # [1, 4, 9, 16, 25]Read it from the middle outwards: **for each n in range(1, 6), give me n * n**. The expression at the front decides what goes into the new list, and the for part says where the values come from. The original data isn't changed; you always get a brand-new list.
Filtering with if
Add an if at the end to keep only some items:
scores = [72, 45, 88, 59, 91]
passed = [s for s in scores if s >= 60] # [72, 88, 91]To change each item depending on a condition rather than filter it out, put a conditional expression at the front instead:
labels = ["pass" if s >= 60 else "fail" for s in scores]The position matters. An if at the end filters items out. An if ... else at the front keeps every item but chooses what it becomes.
Dictionary and set comprehensions
Use curly braces and a key: value expression to build a dictionary:
names = ["ana", "ben", "cleo"]
lengths = {name: len(name) for name in names}
# {'ana': 3, 'ben': 3, 'cleo': 4}Curly braces without a colon build a set, which removes duplicates as it goes: {word.lower() for word in words}. A dictionary comprehension is also a neat way to transform an existing dictionary, for example adding tax to every price: {item: round(p * 1.2, 2) for item, p in prices.items()}.
Generator expressions and nested comprehensions
Swap the square brackets for round brackets and you get a generator expression. It produces values one at a time instead of building a whole list in memory, which is ideal when you only need to feed the values into a function such as sum(), max() or any():
total = sum(n * n for n in range(1, 1_000_001))
has_negative = any(x < 0 for x in readings)When a generator expression is the only argument, you can drop its extra brackets, as above.
A comprehension can contain more than one for. The loops run in the same order as they would if written as nested for statements, outer loop first. This is the standard way to flatten a list of lists:
grid = [[1, 2], [3, 4], [5, 6]]
flat = [n for row in grid for n in row] # [1, 2, 3, 4, 5, 6]Read it as "for each row in grid, for each n in row, keep n". Two loops is usually the readable limit.
Lambda functions, sorted, map and filter
A lambda is a small function written in one expression, without def or a name:
double = lambda x: x * 2You'll rarely store a lambda in a variable like that. Instead, lambdas are passed straight into functions that need a rule. The most common example is sorted() with key=:
people = [("Ana", 15), ("Ben", 13), ("Cleo", 14)]
by_age = sorted(people, key=lambda p: p[1])key tells sorted() which value to compare: here, the age in position 1. max() and min() accept key in the same way. You may also see map(func, items), which applies a function to every item, and filter(func, items), which keeps items where the function returns True. In modern Python, a comprehension usually does the same job more readably.
Python Comprehensions Syntax
Comprehension patterns
[expr for item in items]
[expr for item in items if condition]
[a if condition else b for item in items]
{key: value for item in items}
{expr for item in items}
sorted(items, key=lambda item: item.value)Python Comprehensions Summary
[expression for item in items]builds a new list from any sequence.- An
ifat the end filters items;a if cond else bat the front transforms them. {k: v for ...}builds a dictionary and{x for ...}builds a set.lambda x: ...is a tiny one-expression function, often used withkey=.sorted(),max()andmin()acceptkey=to choose what to compare.- Prefer a plain loop when a comprehension gets hard to read.
Python Comprehensions Examples
Each example shows the code, the output it produces and what each part does.
Cleaning a list of prices
raw = [" 4.50", "12", "", "3.25 ", "n/a", "8.0"]
prices = [float(p) for p in raw if p.strip().replace(".", "").isdigit()]
print(prices)
print("Total:", sum(prices))
with_tax = [round(p * 1.2, 2) for p in prices]
print(with_tax)[4.5, 12.0, 3.25, 8.0]
Total: 27.75
[5.4, 14.4, 3.9, 9.6]Line-by-line explanation
- Line 3Keep only items that look like numbers once spaces and the decimal point are removed, then convert each to a float.
- Line 4The empty string and the text "n/a" have been filtered out.
- Line 7A second comprehension builds a new list with tax added.
Grades for a class
scores = {"Ana": 82, "Ben": 47, "Cleo": 91, "Dev": 63}
grades = {name: ("pass" if s >= 50 else "retake") for name, s in scores.items()}
print(grades)
top = [name for name, s in scores.items() if s >= 80]
print("Distinction:", top){'Ana': 'pass', 'Ben': 'retake', 'Cleo': 'pass', 'Dev': 'pass'}
Distinction: ['Ana', 'Cleo']Line-by-line explanation
- Line 3A dictionary comprehension with a conditional value for every student.
- Line 6A list comprehension that filters names by score.
Sorting with a key
books = [
{"title": "Dune", "year": 1965, "pages": 412},
{"title": "Emma", "year": 1815, "pages": 474},
{"title": "Ubik", "year": 1969, "pages": 202},
]
oldest_first = sorted(books, key=lambda b: b["year"])
print([b["title"] for b in oldest_first])
longest = max(books, key=lambda b: b["pages"])
print("Longest:", longest["title"])
print(sorted(["pear", "Fig", "apple"], key=str.lower))['Emma', 'Dune', 'Ubik']
Longest: Emma
['apple', 'Fig', 'pear']Line-by-line explanation
- Line 7The lambda tells sorted() to compare the books by their year.
- Line 10max() uses the same key idea to find the book with the most pages.
- Line 13Any function can be a key. str.lower makes the sort ignore capital letters.
Common Python Comprehensions Mistakes
Putting else in the wrong place
evens = [n for n in range(10) if n % 2 == 0 else 0]evens = [n if n % 2 == 0 else 0 for n in range(10)]A filtering if at the end can't have an else. To transform every item, move the if/else to the front.
A comprehension just for its side effects
[print(name) for name in names]for name in names:
print(name)Comprehensions are for building collections. Using one only to call print() creates a useless list of None values.
Cramming too much into one line
result = [x * y for x in range(5) if x % 2 for y in range(5) if y > x if x + y < 7]result = []
for x in range(1, 5, 2):
for y in range(x + 1, 5):
if x + y < 7:
result.append(x * y)Python Comprehensions in Real Projects
Comprehensions in real code
Data scripts use comprehensions to clean columns, keep only valid rows and rename fields in one readable step. Web developers use them to turn database rows into the dictionaries a page needs, and sorted(..., key=lambda ...) is the standard way to order search results by price, date or rating.
Python Comprehensions FAQ
Are list comprehensions faster than for loops?
Usually a little, because the appending happens inside Python's internals instead of through a method call on every pass. The difference is modest, though. Choose a comprehension because it expresses "build a list from this data" clearly, not for speed.
Can I use elif in a list comprehension?
Not directly. You can chain conditional expressions, ["high" if s > 80 else "mid" if s > 50 else "low" for s in scores], but this quickly becomes hard to read. For three or more outcomes, write a small function with if/elif and call it inside the comprehension.
Should I use map() and filter() or a comprehension?
In most Python code a comprehension is preferred because it reads left to right and needs no lambda. map() is still neat when you already have a named function, such as list(map(int, parts)). Note that map() and filter() return lazy iterators, so wrap them in list() to see the values.
Why does my generator expression only work once?
A generator produces each value once and is then exhausted. Looping over it a second time gives nothing. If you need the values more than once, build a list with square brackets instead.
Can a lambda contain more than one line?
No. A lambda is limited to a single expression, with no statements such as assignments, loops or return. If you need more than that, define a normal function with def and pass its name instead.
Python Comprehensions Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the comprehension so it builds a list of the numbers doubled.
nums = [1, 2, 3]
doubled = [n * 2 n nums]
What does this print?
print([len(w) for w in ["hi", "hello", "hey"]])
What does this print?
print([n for n in range(1, 11) if n % 3 == 0])
What does this print?
words = ["bb", "a", "ccc"]
print(sorted(words, key=lambda w: len(w)))
Which line builds the dictionary {'a': 'A', 'b': 'B'}?
Python Comprehensions Quiz
5 questions to check what you learned.
What does a list comprehension return?
- The original list, changed
- A new list
- A string
- None
In
[x for x in items if x > 0], what does theifdo?- Keeps only items where the condition is true
- Changes every item
- Stops the loop
- Sorts the items
What is a lambda?
- A loop
- A small, unnamed function written as one expression
- A kind of list
- A module
What does
key=do insorted(items, key=...)?- Encrypts the items
- Removes duplicates
- Tells sorted() which value to compare for each item
- Sorts in reverse
What does
{w.lower() for w in ["A", "a", "B"]}produce?- ['a', 'a', 'b']
- {'A': 'a', 'B': 'b'}
- An error
- {'a', 'b'}