I just stumbled over what seems to be a flaw in the python syntax-- or else I'm missing something.
See this:
[x for x in range(30) if x % 2 == 0]
But this is a syntax error:
[x for x in range(30) if x % 2 == 0 else 5]
If you have an else
clause, you have to write:
[x if x % 2 == 0 else 5 for x in range (30)]
But this is a syntax error:
[x if x %2 == 0 for x in range(30)]
What am I missing? Why is this so inconsistent?
You are mixing syntax here. There are two different concepts at play here:
List comprehension syntax. Here if
acts as a filter; include a value in the iteration or not. There is no else
, as that is the 'don't include' case already.
A conditional expression. This must always return a value, either the outcome of the 'true' or the 'false' expression.
Remember: list comprehensions produce a sequence of values from a loop. By using if
you can control how many elements from the input iterable are used for the output.
A conditional expression on the other hand, works like any other expression: an expression always produces a single result; the conditional expression lets you pick between two possible outcomes. But because it must produce a result you can’t write one without the else
part.
Note that expressions can and are frequently nested. The conditional expression itself contains three sub-expressions:
expr1 if expr2 else expr3
# ^ ^
# \ used when expr2 |
# is true |
# /
# used when expr2 is
# false
List comprehension also contain sub-expressions. The one at the start (before the for <target> in <iterable>
part) is the sub-expression that is executed each iteration to produce the value in the output list. The iterator expression (after in
) is another. The optional if
filter takes an expression too. In any of these places you could use a conditional expression if you so choose. But, that doesn’t mean you can add an extra else
to the list comprehension without the other parts of the conditional expression syntax.
The difference between the two is that the trailing if
in the first one is part of the list comprehension syntax, while the if-else
is the conditional operator, not any part of the list comprehension syntax - as it is an expression which is permitted in that part of a list comprehension.
The syntax for the conditional operator is as follows:
x if condition1 else y
This returns the value of the expression that is evaluated, which is why it seems to "work" for your case, though it evaluates all of the time and returns always - which is the key difference between the two.
Meanwhile, for the list comprehension, it tests whether or not the condition applies, and does not add that in the new list created if the condition does not evaluate to true according to the Truth Value Testing procedure, not None
nor anything else.
Compare the following (taking an example from PEP202):
a = [i if i % 2 == 0 else None for i in range(20)]
b = [i for i in range(20) if i % 2 == 0]
a
would be
[0, None, 2, None, 4, None, 6, None, 8, None, 10, None, 12, None, 14, None, 16, None, 18, None]
while b
would be
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
which isn't the same at all, as no matter what the result of it is, it will still add it in if there is no if
part of the list comprehension.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With