Conditional Comprehensions

The two places an if can appear in a comprehension, which does which, and why only one of them takes an else.

Overview

Filter: the trailing if

[n for n in nums if n % 2 == 0]

This drops items. Six numbers in, three out. The if sits after the for, and it takes no else — there is nowhere for an alternative to go, because a filter either keeps an item or does not.

Writing [n for n in nums if n % 2 == 0 else 0] is a syntax error, and it is worth trying once so the error message becomes familiar.

two_ifs.py

two_ifs.py Python 3
Output

                    

comprehension_conditions.py

comprehension_conditions.py Python 3
Output

                    

Worth knowing

Trailing if = filter. It drops items and takes no else.
if/else in the expression = choose. Every item survives, with one of two values.
Written together, the filter runs first: the expression only sees items that passed.
Two trailing ifs mean the same as one and.

Conditional Comprehensions: A Practical Guide

A comprehension can carry an if in two different places. They do different jobs, only one of them accepts an else, and mixing them up is the single most common comprehension error.

Choose: the conditional expression

["even" if n % 2 == 0 else "odd" for n in nums]

This drops nothing. Six numbers in, six strings out. The if/else is part of the expression at the front — it is the conditional expression from earlier in the track, used inside a comprehension — so it must be complete, and the else is mandatory.

Together

["big" if n > 4 else "small" for n in nums if n % 2 == 0]

Read it in execution order rather than left to right: take each n, keep it only if it is even, then turn what survives into "big" or "small". The filter runs first.

That ordering is not a detail. If the filter is removing None values, the expression never sees them:

["pass" if r["score"] >= 50 else "fail"
 for r in rows if r["score"] is not None]

Swap the two and the comparison raises on the first missing score.

Several filters

[n for n in nums if n % 3 == 0 if n % 5 == 0]

Chained filters mean the same as one and. The and version is usually clearer; the chained form is worth recognising because you will meet it.

In nested comprehensions

[n for row in grid for n in row if n % 2]

A trailing if attaches to the clause it follows — here the inner loop. Placing a filter after the first for instead would filter rows rather than cells. When there are two loops and a condition, this is where a comprehension starts costing more to read than it saves, and the loop version is the kinder choice.

Check yourself

0 of 3

Answer without scrolling back up.

  1. Which position takes an `else`?

  2. `[x for x in xs if c]` and `[a if c else b for x in xs]` differ how?

  3. In a comprehension with both, which runs first?

Cheat sheet

Conditional Comprehensions

A comprehension can carry an if in two different places. They do different jobs, only one of them accepts an else, and mixing them up is the single most common comprehension error.

PYTHON · vizlearn.in/python/conditional_comprehensions.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.