1 in [1,2,3] is True
is evaluated as (1 in [1, 2, 3]) and ([1, 2, 3] is True)
similarly to 1 < 2 < 3
:facepalm: In [1]: import ast
In [2]: print(ast.dump(ast.parse("""\
...: def a():
...: return (1 in [1,2,3] is True)""")))
Module(
body=[
FunctionDef(
name='a',
args=arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
body=[
Return(
value=Compare(
left=Num(n=1),
ops=[In(), Is()],
comparators=[
List(elts=[Num(n=1), Num(n=2), Num(n=3)], ctx=Load()),
NameConstant(value=True)
]
)
)
],
decorator_list=[],
returns=None
)
]
)
In [3]: print(ast.dump(ast.parse("""\
...: def b():
...: return ((1 in [1,2,3]) is True)""")))
Module(
body=[
FunctionDef(
name='b',
args=arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
body=[
Return(
value=Compare(
left=Compare(
left=Num(n=1),
ops=[In()],
comparators=[List(elts=[Num(n=1), Num(n=2), Num(n=3)], ctx=Load())]
),
ops=[Is()],
comparators=[NameConstant(value=True)]
)
)
],
decorator_list=[],
returns=None
)
]
) In [1]: def c():
...: return (1 in ([1,2,3] is True))
In [2]: c()
...
TypeError: argument of type 'bool' is not iterable
It seems related to CPython bytecode compiler implementation, the two functions are parsed in a different way, parentheses make the compiler go on a different path... but I'd like to understand why, without diving into CPython source code :) Anyone? In [1]: import dis
In [2]: def a():
...: return (1 in [1,2,3] is True)
In [3]: def b():
..: return ((1 in [1,2,3]) is True)
In [4]: a()
Out[4]: False
In [5]: b()
Out[5]: True
In [6]: dis.dis(a)
2 0 LOAD_CONST 1 (1)
2 LOAD_CONST 1 (1)
4 LOAD_CONST 2 (2)
6 LOAD_CONST 3 (3)
8 BUILD_LIST 3
10 DUP_TOP
12 ROT_THREE
14 COMPARE_OP 6 (in)
16 JUMP_IF_FALSE_OR_POP 24
18 LOAD_CONST 4 (True)
20 COMPARE_OP 8 (is)
22 RETURN_VALUE
>> 24 ROT_TWO
26 POP_TOP
28 RETURN_VALUE
In [7]: dis.dis(b)
2 0 LOAD_CONST 1 (1)
2 LOAD_CONST 5 ((1, 2, 3))
4 COMPARE_OP 6 (in)
6 LOAD_CONST 4 (True)
8 COMPARE_OP 8 (is)
10 RETURN_VALUE
Why?!