Why does `True == False is False` evaluate to False?

Python

Python Problem Overview


I get some rather unexpected behavior on an expression that works with == but not with is:

>>> (True == False) is False
True
>>> True == (False is False)
True
>>> True == False is False
False
>>> id(True)
8978640
>>> id(False)
8978192
>>> id(True == False)
8978192
>>> id(False is False)
8978640

Python Solutions


Solution 1 - Python

Because in fact that's a chained comparison, so

True == False is False

is equivalent to

(True == False) and (False is False)

This can be surprising in this case, but lets you write 1 <= x < 4 unlike in other languages like C.

Solution 2 - Python

From the docs:

> x < y <= z is equivalent to x < y and y <= z, except that y is > evaluated only once (but in both cases z is not evaluated at all when > x < y is found to be false).

In your case True == False is False is equivalent to True == False and False is False as the first condition is False so it short-circuits and return False.

>>> dis.dis(lambda : True == False is False)
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_GLOBAL              1 (False)
              6 DUP_TOP             
              7 ROT_THREE           
              8 COMPARE_OP               2 (==)
             11 JUMP_IF_FALSE_OR_POP    21          <---------this step
             14 LOAD_GLOBAL              1 (False)
             17 COMPARE_OP               8 (is)
             20 RETURN_VALUE        
        >>   21 ROT_TWO             
             22 POP_TOP             
             23 RETURN_VALUE  

Solution 3 - Python

From the documentation:

> 5.9. Comparisons > > Unlike C, all comparison operations in Python have the same priority, which is lower than that of any arithmetic, shifting or bitwise operation. Also unlike C, expressions like a < b < c have the interpretation that is conventional in mathematics:

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="
                   | "is" ["not"] | ["not"] "in"

Solution 4 - Python

True == False is False is a chained comparison, which means the same as (True == False) and (False is False). Since the first comparison (True==False) is false, the result of the chained comparison is False.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrayluView Question on Stackoverflow
Solution 1 - PythonjorgecaView Answer on Stackoverflow
Solution 2 - PythonAshwini ChaudharyView Answer on Stackoverflow
Solution 3 - PythonSylvainDView Answer on Stackoverflow
Solution 4 - PythonBrenBarnView Answer on Stackoverflow