Python multiple nested ternary expression

Question:

With the Python (2.7) ternary expression x if cond else y what is the logical order when evaluating multiple expressions of these nested in order: e.g.

1 if A else 2 if B else 3

Drawing out the truth table for this is appears this is evaluated as 1 if A else (2 if B else 3) rather than (1 if A else 2) if B else 3:

A      True  False
B                 
True      1      2
False     1      3

Could someone please explain why this is executed in this order, and possibly suggest some material that gives an intuition about why this is used/preferred?

This doesn’t seem obvious when considering the ordering using the inline for statement:

>>>[(i, j, k) for i in range(1) for j in range(2) for k in range(3)]
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 0), (0, 1, 1), (0, 1, 2)]
Asked By: oliversm

||

Answers:

1 if A else 2 if B else 3 translates to this:

def myexpr(A, B):
    if A:
        return 1
    else:
        if B:
            return 2
        else:
            return 3

Your ternary expression can be interpreted with parentheses as follows:

(
 (1 if A) else (
                (2 if B) else 3
               )
)
Answered By: inspectorG4dget

Boolean predicates are in many languages defined to terminate as quickly as possible, as quickly as the end result is known, and especially that the right hand side of an or-expression does not get evaluated at all if the left hand side is true. It really has nothing to do with the destructuring assignment that happens in the list comprehension.

Answered By: Love Tätting

Both uses are one-line cognates of the structures they resemble. inspectorG4dget already laid out the if version for you.
The for clauses nest in the given order:

for i in range(1):
     for j in range(2):
         for k in range(3):
             result.append( (i, j, k) )

The if portion works the same way from the parser’s view: when it hits 1 if A, the parser takes if A as the top-level decision. As defined in the grammar, this nesting is bound from right to left: if B is the innermost (inner-more?).

Answered By: Prune

Could someone please explain why this is executed in this order, and possibly suggest some material that gives an intuition about why this is used/preferred?

I’m trying to answer the "intuition" part of your question by solving a simple but more general problem.

'''
+-----------------------------------------------------------------------------------+
|                                    Problem:                                       |
+-----------------------------------------------------------------------------------+
| Convert a                                                                         |
| nested if-else block into                                                         |
| a single line of code by using Pythons ternary expression.                        |
| In simple terms convert:                                                          |
|                                                                                   |
|      1.f_nested_if_else(*args) (  which uses                                      |
|      ````````````````````        nested if-else's)                                |
|            |                                                                      |
|            +--->to its equivalent---+                                             |
|                                     |                                             |
|                                     V                                             |
|                              2.f_nested_ternary(*args) (     which uses           |
|                              ```````````````````       nested ternary expression) |
+-----------------------------------------------------------------------------------+
'''
'''
Note:
C:Conditions  (C, C1, C2)
E:Expressions (E11, E12, E21, E22)
Let all Conditions, Expressions be some mathematical function of args passed to the function
'''    

#-----------------------------------------------------------------------------------+
#| 1. |      Using nested if-else                                                   |
#-----------------------------------------------------------------------------------+
def f_nested_if_else(*args):
    if(C):
        if(C1):
            return E11
        else:
            return E12
    else:
        if(C2):
            return E21
        else:
            return E22

#-----------------------------------------------------------------------------------+
#| 2. |      Using nested ternary expression                                        |
#-----------------------------------------------------------------------------------+
def f_nested_ternary(*args):
    return ( (E11) if(C1)else (E12) )   if(C)else   ( (E21) if(C2)else (E22) )


#-----------------------------------------------------------------------------------+
#-----------------------------------------------------------------------------------|
#-----------------------------------------------------------------------------------|
#-----------------------------------------------------------------------------------|
#-----------------------------------------------------------------------------------+

Here is a visualization of why f_nested_if_else() and f_nested_ternary() are equivalent.

#     +-----------------------------------------------------------------------------+
#     |                               Visualization:                                |
#     +-----------------------------------------------------------------------------+
#     |         Visualize the ternary expression like a binary tree :               |
#     |           -Starting from the root and  moving down to the leaves.           |
#     |           -All the internal nodes being conditions.                         |
#     |           -All the leaves being expressions.                                |
#     +-----------------------------------------------------------------------------+
                                     _________________
                                     |f_nested_ternary|                                 
                                     ``````````````````
            ( (E11) if(C1)else (E12) )   if(C)else   ( (E21) if(C2)else (E22) )
                |       |        |          |            |       |        |
                |       |        |          |            |       |        |
                V       V        V          V            V       V        V                                                                             
Level-1|                  +----------------(C)-----------------+         
--------             True/          __________________           False         
                        V           |f_nested_if_else|            V              
Level-2|          +----(C1)----+    ``````````````````     +----(C2)----+     
--------     True/              False                True/              False
                V                V                       V                V     
Level-3|    ( (E11)            (E12) )               ( (E21)            (E22) ) 
------------------------------------------------------------------------------------+

Hope this visualization gave you an intuition of how nested ternary expressions are evaluated 😛

Answered By: zurCalleD_suruaT

Can anybody find whats wrong with this code? It gives me syntax error in hackerranks challenges

If __name__ == ‘__main__’:
    n = int(input().strip())
    print(‘Wierd’) if n%2 == 0 else print(‘Not Weird’) if (n%2==0 and 2<=n<=5) else print(‘Weird’) if (n%2==0 and 6<=n<=20) else print(‘Not Weird’) if 20<=n
Answered By: navidabasi