New: 6 free SQL practice datasets with 300+ questions — try the SQL Compiler →
Python

Python List Comprehension Explained Simply

Python list comprehension explained simply: filter, transform, if-else, nested loops, set and dict versions, with real code, output and practice questions.

Upskly AI Team September 26, 2026 8 min read
Python List Comprehension Explained Simply

A Python list comprehension builds a new list in a single line. The pattern is [expression for item in iterable if condition], and it means “give me this expression for each item, keeping only the items that pass the condition”. It does exactly what a for loop with append() does, in a shorter and usually clearer form.

This guide starts from the loop you already know, then builds up to filtering, if-else, nested loops and the other comprehension types. Every example is run, and the output is real.

In this guide

The short version

  • [n * n for n in nums] – transform every item.
  • [n for n in nums if n > 3] – keep only some items.
  • [a if cond else b for n in nums] – pick one of two values (the if-else goes before the for).
  • Curly braces make a set or dict version. Round brackets make a generator.

From a loop to a comprehension

Here is a task you have probably written before: square every number in a list. First with a loop, then with a comprehension:

nums = [1, 2, 3, 4, 5]
squares = []
for n in nums:
    squares.append(n * n)
print(squares)
squares2 = [n * n for n in nums]
print(squares2)
print(squares == squares2)

Output

[1, 4, 9, 16, 25]
[1, 4, 9, 16, 25]
True

The three lines of the loop collapse into one. The comprehension creates the empty list, loops, and appends for you.

The syntax, piece by piece

Anatomy of a list comprehension
PartIn [n * n for n in nums if n > 3]Meaning
Expressionn * nWhat to put in the new list
for clausefor n in numsWhere the items come from
if clause (optional)if n > 3Keep the item only when this is true

A good trick for reading one: start in the middle. Look at the for clause first (where the items come from), then the if (which are kept), and finally the expression at the front (what is produced).

Filtering with if

Adding an if at the end keeps only the items that pass. You can transform and filter in the same comprehension:

nums = [1, 2, 3, 4, 5, 6]
evens = [n for n in nums if n % 2 == 0]
print(evens)
big_squares = [n * n for n in nums if n > 3]
print(big_squares)

Output

[2, 4, 6]
[16, 25, 36]

The second line reads: “give me n * n for each n in the list, but only where n > 3“. Strings work just as well, for example cleaning up messy input:

names = ["  asha ", "RAVI", " meera"]
clean = [n.strip().title() for n in names]
print(clean)
lengths = [len(n) for n in clean]
print(lengths)

Output

['Asha', 'Ravi', 'Meera']
[4, 4, 5]

Using if and else together

If you want every item to produce something, but a different something depending on a condition, use a conditional expression. It goes at the front, before the for:

marks = [90, 45, 72, 30]
result = ["pass" if m >= 40 else "fail" for m in marks]
print(result)

Output

['pass', 'pass', 'pass', 'fail']

This is the most common syntax mistake with comprehensions. The if at the end can only filter, and it cannot have an else:

# Wrong: SyntaxError
[m for m in marks if m >= 40 else 0]

# Right: the if-else goes in front of the for
[m if m >= 40 else 0 for m in marks]

A quick rule: filter with if at the end, choose between two values with if-else at the front.

Nested loops and flattening

You can chain for clauses. They read in the same order as nested loops written out: the first for is the outer loop. This gives you combinations, flattens a list of lists, and even transposes a table:

pairs = [(x, y) for x in [1, 2] for y in ["a", "b"]]
print(pairs)
matrix = [[1, 2, 3], [4, 5, 6]]
flat = [n for row in matrix for n in row]
print(flat)
transposed = [[row[i] for row in matrix] for i in range(3)]
print(transposed)

Output

[(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
[1, 2, 3, 4, 5, 6]
[[1, 4], [2, 5], [3, 6]]

Two levels is fine. Beyond that, a comprehension quickly becomes hard to read, and a plain loop is the kinder choice.

Set, dict and generator versions

The same idea works for other collections. Curly braces with a single expression make a set. Curly braces with key: value make a dictionary:

words = ["apple", "avocado", "banana"]
first_letters = {w[0] for w in words}
print(sorted(first_letters))
lengths = {w: len(w) for w in words}
print(lengths)

Output

['a', 'b']
{'apple': 5, 'avocado': 7, 'banana': 6}

Round brackets do not make a tuple. They make a generator expression, which produces items one at a time instead of building the whole list in memory. That is ideal when you only need to feed the values to something like sum(), which lets you drop the extra brackets:

total = sum(n * n for n in range(1, 4))
print(total)
g = (n * n for n in range(3))
print(type(g).__name__)
print(list(g))

Output

14
generator
[0, 1, 4]

Dictionaries get their own guide: Python Dictionaries Explained With Examples. For how generators work, see Python Iterators and Generators Explained.

When not to use one

  • When you only want side effects. If you are calling print() or saving to a file and do not need a list, use a normal for loop.
  • When the logic needs several steps. If you find yourself squeezing in three conditions and two nested loops, write the loop out. Readable code beats short code.
  • When the data is huge and you only need to loop once. Use a generator expression so you do not hold everything in memory.

Common mistakes

Mistake 1: putting else at the end

As above: use the conditional expression at the front instead.

Mistake 2: using a comprehension just to run a function

It works, but it builds a throwaway list of None values, and it tells the reader you wanted a list when you did not:

result = [print(n) for n in range(3)]
print(result)

Output

0
1
2
[None, None, None]

Use a plain for loop here.

Mistake 3: making it too clever

If a colleague needs a minute to read it, it is too dense. Split it into a loop, or into two steps with a meaningful variable name in between.

Patterns cheat sheet

List comprehension patterns
GoalPattern
Transform every item[f(x) for x in items]
Keep some items[x for x in items if cond]
Transform and keep some[f(x) for x in items if cond]
Choose between two values[a if cond else b for x in items]
Flatten a list of lists[y for row in rows for y in row]
Unique values (set){f(x) for x in items}
Build a dictionary{k(x): v(x) for x in items}
Feed values to sum, max, anysum(f(x) for x in items)

Try it yourself

Write each one as a comprehension, then open the solution.

1. The squares of the odd numbers from 1 to 9.

Show solution
print([n * n for n in range(1, 10) if n % 2 == 1])

Output

[1, 9, 25, 49, 81]

2. The words longer than 3 letters in ["sql", "python", "r", "excel"], in upper case.

Show solution
print([w.upper() for w in ["sql", "python", "r", "excel"] if len(w) > 3])

Output

['PYTHON', 'EXCEL']

3. Flatten [[1, 2], [3], [4, 5]] into one list.

Show solution
print([n for part in [[1, 2], [3], [4, 5]] for n in part])

Output

[1, 2, 3, 4, 5]

The outer for takes each inner list, and the second for takes each number from it.

4. Convert ["1", "2", "3"] to integers and add them up.

Show solution
digits = ["1", "2", "3"]
numbers = [int(d) for d in digits]
print(numbers, sum(numbers))

Output

[1, 2, 3] 6

Try them in our free Python compiler.

Frequently asked questions

What is a list comprehension in Python?

It is a short way to build a list from another iterable in one expression: [expression for item in iterable if condition]. It replaces a loop that creates a list and appends to it.

Are list comprehensions faster than for loops?

Usually a little, because the looping and appending happen inside Python’s optimised machinery. The difference rarely matters, so choose the version that is easier to read, and measure only when speed is a real problem.

Can I use else in a list comprehension?

Yes, but as a conditional expression at the front, not at the end: [a if cond else b for x in items]. An if at the end can only filter.

How do I read a nested list comprehension?

The for clauses read in the same order as nested loops. [n for row in matrix for n in row] means: for each row in matrix, for each n in that row, give me n.

What is the difference between a list comprehension and a generator expression?

A list comprehension (square brackets) builds the whole list in memory. A generator expression (round brackets) produces one item at a time when asked, which saves memory for large data.

Can a comprehension create a dictionary or a set?

Yes. {k: v for ...} builds a dictionary and {x for ...} builds a set.

Run this code in your browser

The free Upskly compiler runs Python with nothing to install. Paste the example, change it and see what happens.

Open Python Compiler

Stuck on a traceback?

AI Assist works inside the Python notebook, so you can ask about an error or a concept without leaving the cell.

Try AI Assist

Test yourself

Timed questions on Control Flow and Comprehensions, with an explanation for every answer.

Take the Quiz
Upskly AI Team
Learning made simple
Scroll to Top