Overview

List comprehensions are one of Python's most distinctive features. They replace multi-line loops with a single expression and are usually faster than equivalent for loops. This tutorial covers syntax, conditions, nested comprehensions, and when not to use them.

Basic Syntax

[expression for item in iterable]

Example: square every number from 0 to 9.

# Loop version
squares = []
for n in range(10):
    squares.append(n * n)

# Comprehension version
squares = [n * n for n in range(10)]

Both produce [0, 1, 4, 9, 16, 25, 36, 49, 64, 81].

Adding a Condition

# Only even numbers
evens = [n for n in range(20) if n % 2 == 0]

# Filter and transform
lengths = [len(word) for word in words if len(word) > 3]

If-Else Inside the Expression

labels = ["even" if n % 2 == 0 else "odd" for n in range(5)]
# ['even', 'odd', 'even', 'odd', 'even']

Note the difference: a trailing if filters items; an inline if/else before the for transforms values.

Nested Loops

pairs = [(x, y) for x in range(3) for y in range(3)]
# [(0,0), (0,1), (0,2), (1,0), ...]

matrix = [[1, 2], [3, 4], [5, 6]]
flattened = [n for row in matrix for n in row]
# [1, 2, 3, 4, 5, 6]

Comprehensions for Other Types

TypeSyntaxResult
List[x for x in it]List
Set{x for x in it}Set (no duplicates)
Dictionary{k: v for k, v in it}Dictionary
Generator(x for x in it)Lazy iterator
# Set comprehension
unique_lengths = {len(w) for w in words}

# Dictionary comprehension
word_lengths = {w: len(w) for w in words}

# Generator (memory efficient)
total = sum(n * n for n in range(1_000_000))

Performance Comparison

import timeit

loop_time = timeit.timeit(
    "result = []\nfor n in range(1000): result.append(n*2)",
    number=10000
)

comp_time = timeit.timeit(
    "result = [n*2 for n in range(1000)]",
    number=10000
)

print(f"Loop: {loop_time:.3f}s, Comprehension: {comp_time:.3f}s")

Comprehensions are typically 20–40% faster because the loop runs in optimized C code rather than Python bytecode.

When Not to Use Comprehensions

  • Complex logic: if the expression needs more than two conditions, a regular loop is clearer.
  • Side effects: comprehensions should produce values, not call print or modify external state.
  • Very large datasets with chaining: use generators to avoid building intermediate lists.
  • Debugging: breakpoints and stack traces are harder to follow inside a comprehension.

Common Mistakes

MistakeCorrect form
[x if x > 0 for x in nums][x for x in nums if x > 0]
[x for x in nums if x > 0 else 0][x if x > 0 else 0 for x in nums]
Using a comprehension for side effectsUse a plain for loop