Python List Comprehensions

Build new lists, dictionaries and sets in one readable line, and use small lambda functions with sorted, map and filter.

Lesson 29 of 107Intermediate18 min read

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:

Python
squares = []
for n in range(1, 6):
    squares.append(n * n)

And here's the same thing as a list comprehension:

Python
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:

Python
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:

Python
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:

Python
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():

Python
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:

Python
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:

Python
double = lambda x: x * 2

You'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=:

Python
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 if at the end filters items; a if cond else b at 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 with key=.
  • sorted(), max() and min() accept key= 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.

Example 1

Cleaning a list of prices

Python
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)
Output
[4.5, 12.0, 3.25, 8.0]
Total: 27.75
[5.4, 14.4, 3.9, 9.6]
Line-by-line explanation
  1. Line 3Keep only items that look like numbers once spaces and the decimal point are removed, then convert each to a float.
  2. Line 4The empty string and the text "n/a" have been filtered out.
  3. Line 7A second comprehension builds a new list with tax added.
Example 2

Grades for a class

Python
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)
Output
{'Ana': 'pass', 'Ben': 'retake', 'Cleo': 'pass', 'Dev': 'pass'}
Distinction: ['Ana', 'Cleo']
Line-by-line explanation
  1. Line 3A dictionary comprehension with a conditional value for every student.
  2. Line 6A list comprehension that filters names by score.
Example 3

Sorting with a key

Python
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))
Output
['Emma', 'Dune', 'Ubik']
Longest: Emma
['apple', 'Fig', 'pear']
Line-by-line explanation
  1. Line 7The lambda tells sorted() to compare the books by their year.
  2. Line 10max() uses the same key idea to find the book with the most pages.
  3. 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

Don't
evens = [n for n in range(10) if n % 2 == 0 else 0]
Do
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

Don't
[print(name) for name in names]
Do
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

Don't
result = [x * y for x in range(5) if x % 2 for y in range(5) if y > x if x + y < 7]
Do
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.

Fill in the blankseasy

Complete the comprehension so it builds a list of the numbers doubled.

nums = [1, 2, 3]
doubled = [n * 2  n  nums]
Predict the outputeasy

What does this print?

print([len(w) for w in ["hi", "hello", "hey"]])
Predict the outputmedium

What does this print?

print([n for n in range(1, 11) if n % 3 == 0])
Predict the outputmedium

What does this print?

words = ["bb", "a", "ccc"]
print(sorted(words, key=lambda w: len(w)))
Multiple choicehard

Which line builds the dictionary {'a': 'A', 'b': 'B'}?

Python Comprehensions Quiz

5 questions to check what you learned.

  1. What does a list comprehension return?

    • The original list, changed
    • A new list
    • A string
    • None
  2. In [x for x in items if x > 0], what does the if do?

    • Keeps only items where the condition is true
    • Changes every item
    • Stops the loop
    • Sorts the items
  3. What is a lambda?

    • A loop
    • A small, unnamed function written as one expression
    • A kind of list
    • A module
  4. What does key= do in sorted(items, key=...)?

    • Encrypts the items
    • Removes duplicates
    • Tells sorted() which value to compare for each item
    • Sorts in reverse
  5. What does {w.lower() for w in ["A", "a", "B"]} produce?

    • ['a', 'a', 'b']
    • {'A': 'a', 'B': 'b'}
    • An error
    • {'a', 'b'}