I am trying to learn list comprehensions Conditionals on iterable. My problem is, I don't understand how my if/else condition working on this list. which if or else working first and printing.
num1 = [5, 10, 15]
num2 = [i**2 if i == 10 else i - 5 if i < 7 else i 5 for i in num1]
print(num2)
Output:
[0, 100, 20]
CodePudding user response:
What you have here is not a list comprehension with conditionals (which filters out some elements of the comprehension), but a post-expression conditional of the form
x = A if (condition) else B
This assigns A if (condition) is true, otherwise it assigns B. (The syntax is a little confusing to look at, it must be admitted, but even Python is not always perfect.) You've managed to stack two of these inside each other, like this:
i**2 if i == 10 else (i-5 if i < 7 else i 5)
Reading from the right: The expression (i-5 if i < 7 else i 5)
will give you i-5
if i<7
, else you get i 5
. Whatever value this is, it is included in the comprehension whenever i==10
is false (so, for the first and third list element).
Note that this construction has nothing to do with a list comprehension; you can use it anywhere (as long as i
is defined).
i = 31
x = i**2 if i == 10 else (i-5 if i < 7 else i 5)
For comparison, here is a real conditional list comprehension: The comprehension will remove values that are equal to 10, leaving you with two elements in the result. I think this is the construction you set out to understand.
num3 = [ i**2 for i in num1 if i != 10 ]
CodePudding user response:
To actually understand how that nested ternary is working, you can write the equivalent branching statement:
num2 = []
for i in num1:
val = i
if i == 10:
val **= 2
elif i < 7:
val -= 5
else:
val = 5
num2.append(val)
Note that no matter what i
is, val
is always assigned a value. This is a requirement for ternary expressions.
In general a ternary expression follows the form
x = expr_if_true if some_condition else expr_if_false
Which is equivalent to
if some_condition:
x = expr_if_true
else:
x = expr_if_false
Notice that expr_if_true
and expr_if_false
can be any valid Python expression, including other ternary expressions. This is the mechanism by which ternary expressions can nest, and this works specifically because ternary expressions always have a return value.
All that said, it's a terrible way to write code. Ternary expressions should be limited to a single level, MAYBE one level of nesting if it can be written concisely and read easily.