DSM
60 XP
30 minsBeginner60 XP

List Comprehensions

By now you've written this loop a dozen times: make an empty list, loop over the data, maybe test each item, append a result. Python noticed how often everyone writes it — and gave it a dedicated one-line syntax. Once comprehensions click, you'll read and write half of real-world Python faster.

What you'll learn

  • Translate a for-append loop into a comprehension and back
  • Add filtering with a trailing if clause
  • Transform conditionally with the value-if-else expression up front
  • Recognize when a comprehension is too dense and a loop reads better
  • Connect comprehensions to the vectorized thinking NumPy and pandas use

What

A list comprehension builds a new list in a single expression: [expression for item in collection if condition]. It's the transform-and-filter loop, compressed — same behavior, same result, one line.

Why

This is the single most common idiom in professional Python. Data code is saturated with it: clean every value, extract one field per record, keep the rows that match. Reading other people's code — Stack Overflow answers, library sources, your teammates' pipelines — requires fluency in it.

Where it's used

Cleaning columns of values, extracting fields from records, filtering rows, building test fixtures, and everywhere a for-append loop used to live.

Where this runs in production

RedditFeed assembly

Ranking code routinely reshapes candidate lists with comprehensions — extracting IDs, filtering removed posts, mapping scores — before the heavy ranking model sees them.

BloombergTick data normalization

Ingest scripts convert raw price strings to floats and drop unparseable ticks in a single comprehension per field — terse enough to audit at a glance.

Hugging FaceDataset preprocessing

Tokenization pipelines are full of comprehensions: [len(t) for t in tokens], [t for t in examples if t['text']] — the shape of virtually all preprocessing code.

Theory

The core ideas, in plain language.

Read a comprehension inside-out from the middle: `for item in collection` names each element, the expression on the LEFT says what each becomes, and an optional `if condition` on the RIGHT filters which ones make it in. The result is always a brand-new list — the original is untouched.
prices = [19.99, 5.49, 12.00]

# The loop you know:
with_tax = []
for p in prices:
    with_tax.append(round(p * 1.08, 2))

# The comprehension — identical result:
with_tax = [round(p * 1.08, 2) for p in prices]
print(with_tax)

Four lines become one, and nothing else changed: same iteration, same transform, same new list. Every comprehension can be mechanically expanded back into its loop — when one confuses you, expand it.

Analogy: The order ticket

A for-append loop is walking the kitchen line telling each cook individually what to do. A comprehension is the order ticket pinned above the pass: 'grilled [expression], for every table [iteration], skip the cancelled ones [filter]'. Same kitchen, same food — the ticket just states the whole job at once.

Key Concept
The two positions of if

A TRAILING if filters — it decides which items get in: [x for x in xs if x > 0]. A LEADING if-else transforms — every item gets in, but conditionally shaped: [x if x > 0 else 0 for x in xs]. Filter selects; conditional expression reshapes. Mixing up the two positions is the #1 comprehension syntax error.

temps = [21.5, -3.0, 18.2, -1.5]

warm_only = [t for t in temps if t > 0]        # filter: 2 items
clamped   = [t if t > 0 else 0.0 for t in temps]  # transform: 4 items
print(warm_only)  # [21.5, 18.2]
print(clamped)    # [21.5, 0.0, 18.2, 0.0]

Same data, both patterns. Filtering can change the length; transforming never does. Choosing between them is a data-design decision you'll make constantly in cleaning code (drop the bad rows, or impute them?).

Comprehensions and NumPy vectorization are the same THOUGHT at different scales: 'apply this to every element' instead of 'here's how to loop'. [t * 9/5 + 32 for t in temps] and temps_array * 9/5 + 32 express identical intent. Practicing comprehensions trains the exact mental muscle pandas expects.
Watch out
Know when to stop

Comprehensions optimize for readability — until they don't. Two nested fors, multiple conditions, or side effects (calling print/save inside one) tip it into write-only code. House rule used by most teams: if it doesn't fit comfortably on one line, or you're doing anything other than building a list, write the loop. A comprehension you have to expand mentally to understand has already failed.

Visual Learning

See the concept, then explore it.

Anatomy of [x * 2 for x in nums if x > 0]

Each element flows right-to-left through the clauses. Click each stage to see its job.

Worked Examples

Watch it built up, one line at a time.

Very EasyTransform every element

Convert a list of names to uppercase for a display board.

Step 1 of 1

Read from the middle: for each n in names, produce n.upper(), collect the results. Three in, three out — a pure transform has no filter clause.

Code
01names = ['ada', 'grace', 'alan']
02shouting = [n.upper() for n in names]
03print(shouting)
Output
['ADA', 'GRACE', 'ALAN']
Practice Coding

Your turn — write the code.

Your task

Clean a day of air-quality sensor readings using only comprehensions — no for-append loops. Build: (1) valid readings (drop the -999 error codes), (2) those same readings rounded to whole numbers, (3) an alert list where readings over 150 become 'HIGH' and the rest 'ok'.

Expected output
Valid: [42.7, 155.2, 89.1, 170.8, 33.4]
Rounded: [43, 155, 89, 171, 33]
Alerts: ['ok', 'HIGH', 'ok', 'HIGH', 'ok']

Write your solution in the editor on the right, then hit Run.

Exercises

Prove it. Reach 80% to complete the lesson.

Mastery Gate0% / 80% required
Easy0/2 solved

What does [n * n for n in range(4)] produce?

Which comprehension keeps only the even numbers from nums, unchanged?

Medium0/3 solved

lengths = [len(w) for w in words if len(w) > 3] — with words = ['data', 'is', 'power']. What is lengths?

ScenarioA teammate submits: results = [process(r) for r in rows if validate(r)] — but process() also WRITES each record to the database, and the return value in results is never used.

What's the code-review feedback?

Given usernames = [' Ada ', 'GRACE', ' alan'], build cleaned — each name stripped of whitespace and lowercased — using one comprehension. Print cleaned. Expected: ['ada', 'grace', 'alan']

Single comprehension:One comprehension with chained .strip().lower() — no loop
Order preserved:Output order matches input order
Hard0/2 solved

Grades: scores = [88, 42, 95, 67, 55, 78]. In ONE comprehension build pass_fail where each score becomes 'pass' if 60 or above, else 'fail' — then print how many passed using .count(). Expected output: ['pass', 'fail', 'pass', 'pass', 'fail', 'pass'] 4

Conditional expression position:if-else must come before the for (transform, not filter)
Same length as input:All six scores produce a label

Which is the best reason to REJECT a comprehension in review and ask for a plain loop?

Complete 80% more exercises to unlock.
Interview Prep

How this shows up in real interviews.

What is a list comprehension, and what are its three clauses?

Show model answer

A list comprehension is an expression that builds a new list from an existing iterable in one statement: [expression for item in iterable if condition]. The for clause is the engine — identical to a loop header, binding each element to a name. The expression says what each element becomes in the output — unchanged, computed, or conditionally shaped with a value-if-else. The optional trailing if filters which elements participate at all. The mental model I'd give: it's exactly the initialize-loop-test-append pattern compressed, and any comprehension can be mechanically expanded back into that four-line loop, which is also the right debugging move when one gets confusing.

Explain the difference between a trailing if and a leading if-else in a comprehension — including the effect on output length.

Show model answer

The trailing if — [x for x in xs if x > 0] — is a FILTER: it sits after the for, takes no else, and decides membership, so the output can be shorter than the input. The leading if-else — [x if x > 0 else 0 for x in xs] — is part of the EXPRESSION: it must have an else, every input element produces exactly one output element, and the length is always preserved. In data-cleaning terms, the trailing if drops bad rows while the leading if-else imputes or caps them — a genuine modeling decision disguised as syntax. The two also fail differently: writing a leading if without else is a SyntaxError, which is usually the first clue someone mixed up the positions.

When would you deliberately choose a plain for loop over a comprehension?

Show model answer

Three cases. First, side effects: if the body writes to a database, prints, or calls an API, a loop states that honestly — a comprehension implies you want the list it builds, and building a throwaway list to smuggle side effects is misleading. Second, complexity: multiple nested fors, several conditions, or logic that no longer fits comfortably on a line — if the reviewer has to mentally expand it, the compression bought nothing. Third, complex accumulation: when iterations depend on previous state (running totals with resets, early exit with break — which comprehensions don't support), the loop's explicit state is clearer. The heuristic I actually use: comprehension when the sentence is 'build a list of X from Y', loop when the sentence contains 'and then' or 'unless'.

Common Mistakes to Avoid

1) Leading if without else — [x if x > 0 for x in xs] is a SyntaxError; filters go at the END. 2) Building a list you never use just to run side effects — use a loop. 3) Nesting comprehensions until they're write-only — expand to a loop when it stops fitting on a line. 4) Filtering when you meant to transform (silently changing the list's length and misaligning it with a paired list). 5) Shadowing an existing variable with the loop name — for n in ns leaks nothing in Python 3, but reusing a meaningful outer name still confuses readers. 6) Reaching for a comprehension over huge numeric data where NumPy vectorization is the real tool.

Ask the AI Tutor

Try these prompts in the AI Tutor panel: • 'Give me five loops to convert into comprehensions, then check my answers.' • 'Show me a comprehension that's too clever and refactor it with me.' • 'Drill me on trailing-if vs leading-if-else with data cleaning examples.' • 'Preview how these comprehensions become pandas one-liners.' • 'Interview mode: ask me when NOT to use a comprehension and grade my answer.'

Glossary

List comprehension — an expression building a new list: [expr for item in iterable if cond]. Expression (in a comprehension) — what each element becomes in the output. Filter clause — the trailing if that decides membership. Conditional expression — value-if-else used as the expression; always needs else. Transform — producing one output element per input element (length preserved). sum() — built-in that totals an iterable. .count(x) — list method counting occurrences of x. Winsorizing — capping outliers at a threshold instead of dropping them. Dict/set comprehension — the same syntax with braces, building dicts or sets. Side effect — an action beyond computing a value (writing, printing).

Recommended Resources

• Docs: 'List Comprehensions' in the official Python tutorial — every variation with examples. • Read: PEP 202, the two-page proposal that added comprehensions — a rare readable language-design document. • Practice: grep any Python codebase you have for 'for' and count how many loops are secretly comprehensions waiting to happen; convert three. • Next in DSM: with control flow complete, you'll stop writing scripts and start building tools — Defining & Calling Functions opens the Functions module, where logic gets a name, inputs, and a returned result.

Recap

✓ [expression for item in collection if condition] — transform on the left, iterate in the middle, filter on the right. ✓ Read comprehensions from the for clause outward; expand to a loop when in doubt. ✓ Trailing if filters (length may shrink); leading if-else transforms (length preserved). ✓ Keep the list you build — side effects belong in loops. ✓ Density is the enemy: one line, one idea, or write the loop. ✓ Comprehensions train the apply-to-every-element thinking that NumPy and pandas run on. Next up: Defining & Calling Functions. Control Flow is complete — you can decide, repeat, steer, and build. Now you'll wrap that logic into named, reusable functions: the unit every pipeline, library, and test is made of.

scratchpad — preview this lesson's challenge anytime
sensor_cleanup.pyPython
Ready
Output

Run your code to see the output here.