DEV Community

Samuel Ochaba
Samuel Ochaba

Posted on

Python Comprehensions Are Declarative (And Why That Matters)

Two ways to square every number in a list:

# Version A
squares = []
for num in numbers:
    squares.append(num ** 2)

# Version B
squares = [num ** 2 for num in numbers]
Enter fullscreen mode Exit fullscreen mode

Version A tells Python how to build the list:

  1. Create empty list
  2. Loop through numbers
  3. Compute square
  4. Append to list
  5. Repeat

Version B tells Python what you want:
"A list of squared numbers."

This is the difference between imperative and declarative code.

Why Declarative Wins

Consider reading code you didn't write. With Version A, you have to trace the loop logic to understand the result. With Version B, the intent is immediate.

More importantly, declarative code is harder to mess up. In Version A, you could:

  • Forget to initialize squares = []
  • Misspell .append() as .appnd()
  • Accidentally append the wrong value
  • Break the loop prematurely

Version B eliminates these failure modes. The pattern is baked in.

The Newspaper Test

Ask yourself: "Can I understand this comprehension in one quick read?"

Passes:

[x ** 2 for x in numbers if x > 0]
Enter fullscreen mode Exit fullscreen mode

Fails:

[(x, y) for x in range(10) for y in range(10)
 if x != y and (x + y) % 2 == 0 and x ** 2 + y ** 2 < 50]
Enter fullscreen mode Exit fullscreen mode

If you have to stop and puzzle it out, the comprehension is too complex. Use a loop instead.

When Loops Are Better

Comprehensions aren't always right. Use loops when:

Multiple statements per item:

for item in items:
    item.validate()
    item.save()
    results.append(item.id)
Enter fullscreen mode Exit fullscreen mode

Side effects:

# DON'T do this - creates useless list of Nones
[print(x) for x in items]

# DO this
for x in items:
    print(x)
Enter fullscreen mode Exit fullscreen mode

Complex control flow:

for x in items:
    if not validate(x):
        continue
    if x.score <= threshold:
        break
    process(x)
Enter fullscreen mode Exit fullscreen mode

The Mindset Shift

Think of comprehensions as expressions that produce collections, not loops that build them.

When you write [f(x) for x in items], you're saying: "This IS a list of f(x) values." Not "This becomes a list through these steps."

Once you internalize this, you'll reach for comprehensions naturally—and know when a loop serves you better.


This is adapted from my upcoming book, Zero to AI Engineer: Python Foundations.
I share excerpts like this on Substack → https://substack.com/@samuelochaba

Top comments (0)