reset password
Author Message
rabbott
Posts: 1649
Posted 18:49 Mar 09, 2019 |

Can you explain the following?

>>> i = 2

>>> (i%2 + 1) == (1 if i%2==0 else 2)
True
>>> i = 0

>>> (i%2 + 1) == (1 if i%2==0 else 2)
True

>>> i = 1

>>> i%2 + 1 == 1 if i%2==0 else 2
2

 

bfazeli
Posts: 6
Posted 19:12 Mar 09, 2019 |

When i = 2
1) (2%2 + 1) == (1 if 2%2 == 0 else 2)
       Evaluation of LE w/ RE (ternary operand (ternary's have 'assignment order' since they return a value))
       1 == 1 -> True
2) Similar logic to 1, but i is now mutated
3) Evaluation of ternary operand w/ another mutation on i, in this case
     if the condition is true it will return a boolean otherwise it returns the val 2
       the evaluation of the ternary condition results in the return val of 2, where 1%2 /= 0 when i = 1
       -->   Can be rewritten as follows for clarity (i%2 + 1 == 1) if (i%2 == 0) else 2 

For more info, ref : https://www.geeksforgeeks.org/ternary-operator-in-python/

Last edited by bfazeli at 19:14 Mar 09, 2019.
rabbott
Posts: 1649
Posted 19:25 Mar 09, 2019 |

I think you have it, but would you provide more elaboration. Your explanation is difficult to follow since it is so compressed.

jpatel77
Posts: 44
Posted 20:14 Mar 09, 2019 |
rabbott wrote:

Can you explain the following?

>>> i = 2

>>> (i%2 + 1) == (1 if i%2==0 else 2)
True
>>> i = 0

>>> (i%2 + 1) == (1 if i%2==0 else 2)
True

>>> i = 1

>>> i%2 + 1 == 1 if i%2==0 else 2
2

 

1. LHS: (0+1) = 1 i.e True since it’s truthy; RHS=(1) since i%2==0 is true = 1 i.e. True since it’s Truthy; therefore LHS = RHS

2. Since 0%2 is 0; therefore same goes as above

3. Pure magic (or a possible bug?) of precedence. Mod is evaluated first, which returns 1, then + which returns 2, then == which returns False i.e. 0 as well, and finally ternary, which anyway retuns false case i.e. 2.

Edit: I think this has more to it since I just learned if else has higher precedence. Have to look at it.

Edit 2: My bad. This table lists the precedence in least to most binding order which made me confused. So ignore all edits: 

https://docs.python.org/3/reference/expressions.html#operator-precedence


 

Last edited by jpatel77 at 20:49 Mar 09, 2019.
jungsoolim
Posts: 38
Posted 20:28 Mar 09, 2019 |

I tested few cases. Based on the experiments, the if-then-else function has higher precedence than mod, add, and comparison.

If-then-else is evaluated first. Then %, +, and finally ==.

(Maybe?)

i=1
i%2 + 1 == 1 if i%2==0 else 2
2
i%2 + 1 == 1 if i%2==0 else 100
100
i%2 + 1 == 1 if i%2 !=0 else 100
False
i%2 + 1 == 1 if i%2 == 1 else 100
False
i%2 + 1 == 1 if i%3 == 77 else 77
77
i%2 + 1 == 1 if i%2 == 77 else 77
77
i%2 + 1 == 1 if i%2 != 77 else 77
False
 

jpatel77
Posts: 44
Posted 20:36 Mar 09, 2019 |
jungsoolim wrote:

I tested few cases. Based on the experiments, the if-then-else function has higher precedence than mod, add, and comparison.

If-then-else is evaluated first. Then %, +, and finally ==.

(Maybe?)

i=1
i%2 + 1 == 1 if i%2==0 else 2
2
i%2 + 1 == 1 if i%2==0 else 100
100
i%2 + 1 == 1 if i%2 !=0 else 100
False
i%2 + 1 == 1 if i%2 == 1 else 100
False
i%2 + 1 == 1 if i%3 == 77 else 77
77
i%2 + 1 == 1 if i%2 == 77 else 77
77
i%2 + 1 == 1 if i%2 != 77 else 77
False
 

Don't you think it gave these outputs because the ternary is evaluated at the end?

Last edited by jpatel77 at 20:48 Mar 09, 2019.
jungsoolim
Posts: 38
Posted 21:07 Mar 09, 2019 |

Yes, you are right. If the condition is true, the first part is evaluated. Otherwise it evaluates the else part.

i = 1
i%2 + 1 == 2 if i%2==1 else 2
True
i%2 + 1 == 1 if i%2 == 1 else 2
False

Thus, it is same with 

(i%2 + 1 == 1) if i%2 == 0 else 2
2
(i%2 + 1 == 1) if i%2 != 0 else 2
False

Or, it is equivalent with

(i%2 + 1 == 1, 2)[i%2 ==0]
False
(i%2 + 1 == 1, 2)[i%2 !=0]
2

The first part is for true condition, and the second part is for false condition.

(i%2 + 1 == 1, 77)[i%2 !=0]
77

(i%2 + 1 == 1) if i%2 != 0 else (i%2 + 1 == 2)
False
(i%2 + 1 == 1) if i%2 == 0 else (i%2 + 1 == 2)
True

(Maybe ?)

 

Last edited by jungsoolim at 21:12 Mar 09, 2019.
jpatel77
Posts: 44
Posted 21:16 Mar 09, 2019 |
Or, it is equivalent with

(i%2 + 1 == 1, 2)[i%2 ==0]
False
(i%2 + 1 == 1, 2)[i%2 !=0]
2

The first part is for true condition, and the second part is for false condition.

(i%2 + 1 == 1, 77)[i%2 !=0]
77

 

 

This is so clever! I really liked this one. And yes, you’re right.

asharm33
Posts: 2
Posted 00:08 Mar 10, 2019 |

1. Case when i = 2 and the expression is `(i%2 + 1) == (1 if i%2==0 else 2)`, then it works following way:
    - First, it solves LHS and RHS brackets are solved. So, for LHS, (2%2 + 1) is 1 and, for RHS, (1 if 2%2==0 else 2) also becomes 1 since if condition is true.
    - Since, LHS and RHS are both 1. Therefore, it returns TRUE.
2. Case when i = 0 and the expression is `(i%2 + 1) == (1 if i%2==0 else 2)`, then:
    - Again it solves the brackets first for LHS and RHS. So, for LHS (0%2 + 1) is 1 and, for RHS, (1 if 0%2==0 else 2) also becomes 1 since if conditions is true (as 0%2 is 0).
    - Since, both LHS and RHS are 1. Therefore, it again returns TRUE.
3. To better understand the third case lets consider simplifying and rewriting it first the following way:
    ```
        i=1
        if i%2==0:
            i%2 + 1 == 1
        else:
            2
    ```
    - Since i = 1, the if condition fails because 1%2 is equal to 1, therefore it returns 2 from else condition.

 

rabbott
Posts: 1649
Posted 13:22 Mar 10, 2019 |
rabbott wrote:

Can you explain the following?

>>> i = 2

>>> (i%2 + 1) == (1 if i%2==0 else 2)
True
>>> i = 0

>>> (i%2 + 1) == (1 if i%2==0 else 2)
True

>>> i = 1

>>> i%2 + 1 == 1 if i%2==0 else 2
2

 

Nice discussion!

As Jay pointed out, the key is the precedence of the operators. (See the table he linked to.)  The == operator binds more tightly than the if-else ternary operator. Notice that the third example (deliberately) doesn't have the parentheses the first two have. If they were put in, the result would be True as in the other examples. 

>>> (i%2 + 1) == (1 if i%2==0 else 2)
True

 

Last edited by rabbott at 13:23 Mar 10, 2019.
rabbott
Posts: 1649
Posted 13:25 Mar 10, 2019 |

That raises a second (easier) challenge.

Apparently i%2 + 1 and 1 if i%2==0 else 2 are equivalent. I.e., they always return the same result. What's the simplest way to prove that?

P.S. It really is easy to prove.

Last edited by rabbott at 13:26 Mar 10, 2019.
dvariya
Posts: 3
Posted 14:35 Mar 10, 2019 |

They will always produce the same result because:

i % 2 will either return 0 or 1. (no values other than 0/1)

When i % 2  returns 0:

"i%2+1" evaluates to 1
and 
"1 if i%2==0 else 2" satisfies the if check and returns 1.

In a similar way,
When i % 2  returns 1:

"i%2+1" evaluates to 2
and 
"1 if i%2==0 else 2" does not satisfy the if check and returns 2

rabbott
Posts: 1649
Posted 15:18 Mar 10, 2019 |

That's good.  Can you (or anyone) show how to transform 1 if i%2==0 else 2 into i%2 + 1 by simple substitution and some minor algebraic manipulation?

Last edited by rabbott at 15:19 Mar 10, 2019.
dvariya
Posts: 3
Posted 16:03 Mar 10, 2019 |

Not sure, If I have understood correctly.

In order to transform, we can use Bitwise AND as shown below:

a = (i & 1) + 1

print(a)

jpatel77
Posts: 44
Posted 16:20 Mar 10, 2019 |
rabbott wrote:

That's good.  Can you (or anyone) show how to transform 1 if i%2==0 else 2 into i%2 + 1 by simple substitution and some minor algebraic manipulation?

I would say:

1 if i%2==0 else 2
= (0 if i%2==0 else 1 ) + 1
= (i%2) + 1 ; since both 0 if i%2==0 else 1 and i%2 gives 0 for even 1 for odds.
= i%2 + 1 ; can eliminate parentheses as % binds tighter than + 

Last edited by jpatel77 at 16:21 Mar 10, 2019.
rabbott
Posts: 1649
Posted 19:42 Mar 10, 2019 |

Terrific! Just what I was hoping for.

Another way of putting the next to last step is as follows.

A tautological way to write i%2 is

0 if i%2 == 0 

i%2 =                              = 0 if i%2 == 0 else 1

1 if i%2 == 1

Last edited by rabbott at 19:47 Mar 10, 2019.