Python's list comprehensions can have an optional condition at the end to filter down results, using the if keyword.
But what if you don't want to filter down results, but instead you'd like to have one expression evaluated or another?
Can a comprehension use an if with an else?
Do list comprehensions support else?
This list comprehension isn't valid:
>>> counts = [2, -1, 4, 7, -3, 6]
>>> sanitized_counts = [n for n in counts if n > 0 else 0]
File "<stdin>", line 1
sanitized_counts = [n for n in counts if n > 0 else 0]
^^^^
SyntaxError: invalid syntax
Python's list comprehensions don't have any support for an else keyword.
But else does work in comprehensions...
But wait!
I've seen else in a comprehension before.
This comprehension works fine:
>>> sanitized_counts = [n if n > 0 else 0 for n in counts]
This gives us all of the same numbers as before, but all the negative numbers are turned into zeros instead:
>>> counts = [2, -1, 4, 7, -3, 6]
>>> sanitized_counts
[2, 0, 4, 7, 0, 6]
How does that work?
Python's ternary operator
Well, that else isn't actually part of the comprehension, and neither is the if.
This is Python's version of a ternary operator:
>>> n = 5
>>> n if n > 0 else 0
5
This expression checks a condition and evaluates one expression if the condition is truthy, or another expression if the condition is falsey:
>>> n = -3
>>> n if n > 0 else 0
0
These are sometimes called inline if expressions or conditional expressions.
This is what we saw at the beginning of our comprehension before:
>>> counts = [2, -1, 4, 7, -3, 6]
>>> sanitized_counts = [n if n > 0 else 0 for n in counts]
Conditional expressions in list comprehension
So the mapping part of this comprehension has an inline if within it.
Here's the same comprehension written over multiple lines of code (see breaking code over multiple lines in Python):
>>> sanitized_counts = [
... n
... if n > 0
... else 0
... for n in counts
... ]
Those first three lines are not part of the comprehension syntax, but are instead a single expression that happens to be inside our comprehension.
Making more readable list comprehensions
I often prefer to write my list comprehensions over multiple lines of code.
But this comprehension is a little bit deceptive because it looks like each component of our inline if is actually part of our comprehension syntax:
>>> sanitized_counts = [
... n
... if n > 0
... else 0
... for n in counts
... ]
We could make this a bit more readable by putting all three components of that conditional expression on one line:
>>> sanitized_counts = [
... n if n > 0 else 0
... for n in counts
... ]
I'd prefer to take this even further by wrapping parentheses around that first expression, to make it clearer that it's not actually part of the comprehension syntax itself:
>>> sanitized_counts = [
... (n if n > 0 else 0)
... for n in counts
... ]
Folks reading our code who've never seen an inline if embedded in a comprehension will probably find this a bit easier to understand.
Avoid complex comprehensions
Simpler comprehensions are often easier to read than more complex ones.
So we might even consider moving that first conditional expression out of our comprehension and into its own function:
>>> def negatives_to_zero(n):
... return n if n > 0 else 0
...
>>> sanitized_counts = [negatives_to_zero(n) for n in counts]
Sometimes an inline if is readable enough.
But the more complex they are, the more I'd hesitate to embed them inside a larger expression.
Python's list comprehensions and if-else
Python's list comprehensions do not support the else keyword.
But there's nothing stopping us from embedding a conditional expression within a comprehension.
Just keep readability in mind when you're embedding a large expression within a comprehension.
A Python tip every week
Need to fill-in gaps in your Python skills?
Sign up for my Python newsletter where I share one of my favorite Python tips every week.
List comprehensions can improve code readability. Python's for loops are general-purpose tools. List comprehensions are special-purpose tools, which convey their meaning more quickly at a glance.