Python Basics — List Comprehensions

3 minute read

List Comprehensions

List comprehensions provide a concise way to create lists. They are one of Python’s most loved features.

Basic Syntax

[expression for item in iterable]
# Traditional loop
squares = []
for x in range(10):
    squares.append(x ** 2)

# List comprehension
squares = [x ** 2 for x in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

With Conditional Filtering

[expression for item in iterable if condition]
# Even numbers only
evens = [x for x in range(20) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Words longer than 3 characters
words = ["hi", "hello", "hey", "howdy", "go"]
long_words = [w for w in words if len(w) > 3]
print(long_words)  # ['hello', 'howdy']

With if-else (Ternary)

When you need else, the expression goes before for:

# Label even/odd
labels = ["even" if x % 2 == 0 else "odd" for x in range(6)]
print(labels)  # ['even', 'odd', 'even', 'odd', 'even', 'odd']

Key difference:

  • Filter (no else): [x for x in items if condition]
  • Transform (if-else): [a if condition else b for x in items]

Multiple for Clauses (Nested)

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

This is equivalent to:

pairs = []
for x in range(3):
    for y in range(3):
        pairs.append((x, y))

Flattening a 2D List

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

Comprehension vs map() and filter()

numbers = [1, 2, 3, 4, 5]

# Using map + filter
result = list(map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, numbers)))

# Using comprehension (more readable)
result = [x ** 2 for x in numbers if x % 2 == 0]

print(result)  # [4, 16]

Comprehensions are generally preferred for readability. Use map()/filter() when the function already exists:

words = ["hello", "WORLD", "Python"]
lower = list(map(str.lower, words))  # cleaner with existing method
# vs
lower = [w.lower() for w in words]   # also fine

Performance Notes

List comprehensions are slightly faster than equivalent for loops because the loop runs at C speed internally:

import timeit

# Loop approach
def with_loop():
    result = []
    for i in range(1000):
        result.append(i ** 2)
    return result

# Comprehension approach
def with_comp():
    return [i ** 2 for i in range(1000)]

print(timeit.timeit(with_loop, number=10000))
print(timeit.timeit(with_comp, number=10000))  # ~20-30% faster

When NOT to Use Comprehensions

Avoid comprehensions when they become hard to read:

# ❌ Too complex — use a regular loop
result = [
    transform(x, y)
    for x in range(10)
    for y in range(10)
    if x != y
    if is_valid(x, y)
]

# ✅ Better as a loop
result = []
for x in range(10):
    for y in range(10):
        if x != y and is_valid(x, y):
            result.append(transform(x, y))

Guidelines

Use Comprehension When… Use Loop When…
Simple transformation Complex logic
One or two conditions Multiple conditions
Result fits in one line Side effects needed
Easy to read at a glance Debugging required

Dictionary and Set Comprehensions (Preview)

Python also supports comprehensions for other collections:

# Dictionary comprehension
squares_dict = {x: x ** 2 for x in range(6)}
print(squares_dict)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# Set comprehension
unique_lengths = {len(w) for w in ["hi", "hello", "hey"]}
print(unique_lengths)  # {2, 5, 3}

We will cover these in detail in the Dictionaries and Sets chapters.

Summary

  • [expr for item in iterable] — basic comprehension
  • [expr for item in iterable if cond] — with filter
  • [a if cond else b for item in iterable] — with transform
  • Nested for clauses for cartesian products and flattening
  • Prefer comprehensions for simple, readable transformations
  • Fall back to regular loops for complex logic

Next up: Nested Lists →

Updated: