Part 5 of 6 · Chapter 2 of 4

Building a Collection in One Line

Building a new list from an old one usually starts as three lines: an empty list, a loop, and an append. Write the same transformation as one line, and read it back exactly as fast as you wrote it.

Intermediate9 min read

Worth reading first: Doing Something More Than Once


Building a new list from an old one usually starts as three lines: an empty list, a loop, and an append. Write the same transformation as one line, and read it back exactly as fast as you wrote it.

The three-line version, first

squares = [] starts empty. The loop runs once per number, and squares.append(n * n) grows the list by one each time. Nothing here is wrong — it is just three lines to say one idea.

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

The loop version

squares = []
for n in numbers:
    squares.append(n * n)

The comprehension

squares = [n * n for n in numbers]

squares

149162536

Both versions produce the exact same list. The comprehension just says it in the order you would say it out loud: what to compute, then what to loop over, then which ones to keep.

The same idea, written as one expression

[n * n for n in numbers] is a list comprehension: the same loop and the same append, written in the order you would say it aloud — “n squared, for every n in numbers”. Adding if n % 2 == 0at the end filters which values make it in, doing the work of the loop's if check without a separate line.

When a comprehension makes code harder to read, not easier

A comprehension earns its place when the body is one short expression. Nest two loops inside it, or stack three conditions, and it stops being readable in one glance — at that point the three-line loop is the clearer choice, not a worse one.

Key takeaways

  • A list comprehension is a loop and an append, written as one expression in the order you'd say it aloud.
  • [expression for item in iterable] builds the list; adding if condition at the end filters which items are kept.
  • Both forms produce identical output — there is no performance or correctness reason to prefer one over the other for simple cases.
  • Once the body needs nested loops or several conditions, a plain loop reads more clearly than a comprehension does.