Comprehensions are Python's way of building collections from iterables in a single, declarative expression. You'll use them daily — filtering API responses, reshaping data for templates, deduplicating records, constructing lookup dicts. They replace the pattern of "create empty collection, loop, append" with something that reads closer to the intent.
But comprehensions aren't just shorter syntax for loops. They signal to the reader that the result is a new collection derived from a transformation. A well-written comprehension is immediately scannable. A poorly-written one — three nested for clauses with two if conditions — is worse than the loop it replaced. Knowing where that line sits is what separates clean Python from clever Python.
Master python list comprehensions
Take the Python Fundamentals course with hands-on lessons and challenges.
This is the most common real-world use: take raw data, filter it, and reshape it into the structure your downstream code expects. The comprehension replaces six lines of loop-and-append with a single expression that reads top-down.
Dict comprehensions replace the awkward pattern of initializing an empty dict and setting keys in a loop. The config extraction pattern (filtering env vars by prefix and stripping it) is something you'll use in every non-trivial Python service.
Set comprehensions combine transformation and deduplication in one pass. Without them, you'd transform first into a list, then wrap it in set(), doing two iterations. The set comprehension does both at once and makes the intent — unique results from a transformation — immediately clear.
The read order for nested comprehensions matches nested for-loops: outer loop first, inner loop second. For the flatten example, read it as 'for each scores list, for each score in that list, keep it if >= 70'. The transpose is the practical limit of nesting — anything deeper should be a loop or a library call.
Generator expressions are comprehensions that produce values lazily. When you pass one to sum(), any(), or all(), only one element is in memory at a time. For large datasets — log files, CSV exports, database cursors — this is the difference between a working script and an OOM kill.
The walrus operator (:=) assigns the result of an expression so you can use it in both the if-clause and the output expression. Without it, you'd either call the function twice or fall back to a loop. It's particularly valuable with regex matching and any operation where the filter check produces the value you want to keep.
Nesting three or more for-clauses in a single comprehension — it becomes unreadable and harder to debug than the equivalent loops
If you need more than two levels of iteration, break it into a helper function or use explicit loops. A comprehension should be scannable in under five seconds. When you need to add a comment explaining the comprehension's logic, it's too complex.
Using a list comprehension when you only need to iterate once — `sum([x**2 for x in data])` allocates the entire list before summing
Drop the brackets: `sum(x**2 for x in data)`. This passes a generator expression directly to sum(), which processes elements one at a time. The same applies to `any()`, `all()`, `min()`, `max()`, and `"".join()`.
Confusing the position of the if-else expression vs. the if filter — writing `[x if x > 0 for x in data]` which is a SyntaxError
If-else (ternary) goes before the `for`: `[x if x > 0 else 0 for x in data]`. A filter condition goes after the `for`: `[x for x in data if x > 0]`. They serve different purposes — one transforms, the other filters.
Using comprehensions for side effects — e.g. `[print(x) for x in items]` — which builds a useless list of None values
Use a regular for-loop for side effects: `for x in items: print(x)`. Comprehensions are for building new collections, not for executing actions. The `[None, None, ...]` list gets created and immediately thrown away.
Comprehensions are Python's declarative syntax for building lists, dicts, and sets from iterables. List comprehensions handle filtering and transforming data in a single expression. Dict comprehensions build lookup tables and remap keys. Set comprehensions deduplicate during transformation. Generator expressions do the same work lazily, which matters when processing large datasets. The walrus operator lets you capture intermediate results in the filter clause to avoid redundant computation. The key judgment call is readability: if a comprehension needs a comment to explain it, it should be a loop or a function call instead.
Interactive lessons and challenges on Stanza, practice in VS Code, Cursor, or the web.
Interactive lessons and challenges, right in your code editor.
Check the free courses. No credit card.