This question is asked out of purely curiosity/academic interest of Python as a language.
Suppose I have the following snippet:
>>> 1 in [1,2] == False
False
Which come out as expected as in
takes precedence over ==
and 1 in [1,2] evaluates to True
, and True != False
.
But behold:
>>> 10 in [1,2] == False
False
Which is surprising because 10 in [1,2] evaluates to False
and False == False
should evaluates to True
.
And I can prove that it is not because ==
is evaluated first, because it wouldn't even run:
>>> 10 in ([1,2] == False)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argument of type 'bool' is not iterable
While if in
statement is run first by parenthesis it will return True
:
>>> (10 in [1,2]) == False
True
# Note: All of above work in the same way if numbers and list are substituted by variables.
I went to dis
and discovered an interesting caveat:
def func(): return (x in y == False)
dis.dis(func)
0 LOAD_FAST 0 (x)
2 LOAD_FAST 1 (y)
4 DUP_TOP
6 ROT_THREE
8 COMPARE_OP 6 (in)
10 JUMP_IF_FALSE_OR_POP 18
12 LOAD_CONST 1 (False)
14 COMPARE_OP 2 (==)
16 RETURN_VALUE
>> 18 ROT_TWO
20 POP_TOP
22 RETURN_VALUE
The JUMP_IF_FALSE_OR_POP
bytecode entirely skips the ==
part (to 18) if FALSE. However, doing x in y == True
also always evaluate to True on essentially the same bytecode. What's more, This bytecode is not seen in either in
or ==
operations, something has to be generating it.
So what exactly is going on here? Why does everything in the format of x in y == (bool)
Always evaluate to False
? And what's actually happening behind the scene?