← Home

085. List Comprehensions

Build lists concisely with expressions instead of append loops

085. List Comprehensions

He has a list of Process objects. He wants three derived lists: RSS in MB, only the heavy processes, and RSS scaled to GB.

His first attempt: three separate loops with append.

A senior dev shows him list comprehensions:

processes = [
    {"name": "chrome",  "rss_mb": 620},
    {"name": "python",  "rss_mb": 85},
    {"name": "slack",   "rss_mb": 310},
    {"name": "vim",     "rss_mb": 12},
]

# Extract: all RSS values
rss_values = [p["rss_mb"] for p in processes]
# β†’ [620, 85, 310, 12]

# Filter: only heavy processes (> 200 MB)
heavy = [p for p in processes if p["rss_mb"] > 200]
# β†’ [{chrome, 620}, {slack, 310}]

# Transform + filter: GB values for heavy processes
heavy_gb = [p["rss_mb"] / 1024 for p in processes if p["rss_mb"] > 200]
# β†’ [0.605..., 0.302...]

Three operations, three one-liners. Readable, no intermediate state.


πŸ’‘ Fun fact: List comprehensions in Python were inspired by set-builder notation in mathematics and by the list comprehensions in Haskell. They were added in Python 2.0 (2000) and were so well-received that Python later added dict comprehensions (Python 2.7/3.0), set comprehensions, and generator expressions using the same syntax pattern.

⚠️ Watch out: The most common mistake is putting the if condition in the wrong place. [f(x) if cond else g(x) for x in items] is a conditional expression that transforms every element. [f(x) for x in items if cond] is a filter that skips elements. They look similar but do completely different things.

πŸ€” Think about it: [x * 2 for x in range(1_000_000)] builds a list of one million integers in memory immediately. (x * 2 for x in range(1_000_000)) is a generator that produces values one at a time. When would the generator version be significantly better, and are there cases where you’d prefer the list despite the memory cost?

Learning objectives

  • Write list comprehensions as an alternative to append loops
  • Add filter conditions to list comprehensions
  • Apply transformations to each element

Key concepts

  • list comprehension
  • filter condition
  • expression
  • Pythonic style

Try it

Concept detail

List comprehension syntax: [expression for variable in iterable] [expression for variable in iterable if condition]

Examples: [ii for i in range(1, 6)] β†’ [1, 4, 9, 16, 25] [x for x in nums if x % 2 == 0] β†’ even numbers only [c9/5+32 for c in temps] β†’ Celsius β†’ Fahrenheit [p[β€œname”] for p in processes] β†’ extract a field

Reading it: β€œgive me [expression] for each [variable] in [iterable] where [condition]”

Compared to append loop: # Loop: result = [] for x in items: if x > 0: result.append(x * 2)

# Comprehension β€” same thing, one line:
result = [x * 2 for x in items if x > 0]

Nested comprehension (flatten a 2D list): [cell for row in matrix for cell in row]

Generator expression (lazy β€” no list in memory): (x*2 for x in items) # use when you only need to iterate once

When to use comprehensions:

  • Single expression per element: ideal
  • Simple filter condition: ideal
  • Multiple lines of logic per element: use a regular loop for clarity

Solution

def squares(n):
    return [i * i for i in range(1, n + 1)]

def even_numbers(numbers):
    return [x for x in numbers if x % 2 == 0]

def celsius_to_fahrenheit(temps):
    return [c * 9 / 5 + 32 for c in temps]

Tests

def test_squares():
    assert squares(5) == [1, 4, 9, 16, 25]

def test_squares_one():
    assert squares(1) == [1]

def test_squares_empty():
    assert squares(0) == []

def test_even_numbers():
    assert even_numbers([1, 2, 3, 4, 5, 6]) == [2, 4, 6]

def test_even_empty():
    assert even_numbers([1, 3, 5]) == []

def test_even_negatives():
    assert even_numbers([-4, -3, -2, -1, 0]) == [-4, -2, 0]

def test_celsius_freezing():
    result = celsius_to_fahrenheit([0, 100])
    assert abs(result[0] - 32.0) < 0.001
    assert abs(result[1] - 212.0) < 0.001

def test_celsius_body():
    result = celsius_to_fahrenheit([37])
    assert abs(result[0] - 98.6) < 0.1

Resources