You have [1, 2, 3] and you want [2, 4, 6]. In a loop, you'd write four lines: init an empty list, iterate, append each doubled value, return. What if I told you Python has a one-line version that expresses exactly the same intent?
I've seen brackets with a for inside them — [x*2 for x in nums] — but I've never actually written one from scratch. Is that what you mean?
That's exactly it. A list comprehension is a loop you can write in one line. Same logic, tighter syntax. Here it is side by side:
# Loop version
result = []
for x in nums:
result.append(x * 2)
# Comprehension (identical output)
result = [x * 2 for x in nums]So the x * 2 before the for is what gets collected, and the for x in nums is the iteration part? Reading left to right feels backwards from the loop.
Read it as "give me x * 2, for each x in nums". The collected expression comes first — which matches how you'd describe the output aloud. Once you see it that way, it flows naturally:
def double_numbers(nums: list) -> list:
return [x * 2 for x in nums]One line replaces four. No intermediate list, no manual append, no off-by-one risk.
What happens if nums is empty? Does the comprehension crash?
It returns []. Comprehensions iterate over whatever is there — nothing to iterate, nothing to collect. No special case needed for empty input. That's one of the reasons they're safer than loops: you can't forget to initialize the accumulator.
So any time I catch myself building an empty list and appending in a loop, I should reach for a comprehension first?
That's the instinct to build. Comprehensions communicate intent — "transform this into that" — without the scaffolding. The loop is still valid, but the comprehension is the idiomatic Python expression for a pure transformation.
TL;DR: [expr for x in xs] is the one-line version of build-empty-list-then-append.
result = []; for x in xs: result.append(f(x)) → 3 lines, mutable state[f(x) for x in xs] → 1 expression, no state[] automatically, no guard needed| Piece | Role |
|---|---|
expr | what gets collected |
for x in xs | the iteration |
Read aloud as: "expr, for each x in xs."
You have [1, 2, 3] and you want [2, 4, 6]. In a loop, you'd write four lines: init an empty list, iterate, append each doubled value, return. What if I told you Python has a one-line version that expresses exactly the same intent?
I've seen brackets with a for inside them — [x*2 for x in nums] — but I've never actually written one from scratch. Is that what you mean?
That's exactly it. A list comprehension is a loop you can write in one line. Same logic, tighter syntax. Here it is side by side:
# Loop version
result = []
for x in nums:
result.append(x * 2)
# Comprehension (identical output)
result = [x * 2 for x in nums]So the x * 2 before the for is what gets collected, and the for x in nums is the iteration part? Reading left to right feels backwards from the loop.
Read it as "give me x * 2, for each x in nums". The collected expression comes first — which matches how you'd describe the output aloud. Once you see it that way, it flows naturally:
def double_numbers(nums: list) -> list:
return [x * 2 for x in nums]One line replaces four. No intermediate list, no manual append, no off-by-one risk.
What happens if nums is empty? Does the comprehension crash?
It returns []. Comprehensions iterate over whatever is there — nothing to iterate, nothing to collect. No special case needed for empty input. That's one of the reasons they're safer than loops: you can't forget to initialize the accumulator.
So any time I catch myself building an empty list and appending in a loop, I should reach for a comprehension first?
That's the instinct to build. Comprehensions communicate intent — "transform this into that" — without the scaffolding. The loop is still valid, but the comprehension is the idiomatic Python expression for a pure transformation.
TL;DR: [expr for x in xs] is the one-line version of build-empty-list-then-append.
result = []; for x in xs: result.append(f(x)) → 3 lines, mutable state[f(x) for x in xs] → 1 expression, no state[] automatically, no guard needed| Piece | Role |
|---|---|
expr | what gets collected |
for x in xs | the iteration |
Read aloud as: "expr, for each x in xs."
Write `double_numbers(nums)` that returns a new list with every number in `nums` multiplied by 2. Use a list comprehension.
Tap each step for scaffolded hints.
No blank-editor panic.