Why does "not(True) in [False, True]" return False? Why does "not(True) in [False, True]" return False? python python

Why does "not(True) in [False, True]" return False?


Operator precedence 2.x, 3.x. The precedence of not is lower than that of in. So it is equivalent to:

>>> not ((True) in [False, True])False

This is what you want:

>>> (not True) in [False, True]True

As @Ben points out: It's recommended to never write not(True), prefer not True. The former makes it look like a function call, while not is an operator, not a function.


not x in y is evaluated as x not in y

You can see exactly what's happening by disassembling the code. The first case works as you expect:

>>> x = lambda: False in [False, True]>>> dis.dis(x)  1           0 LOAD_GLOBAL              0 (False)              3 LOAD_GLOBAL              0 (False)              6 LOAD_GLOBAL              1 (True)              9 BUILD_LIST               2             12 COMPARE_OP               6 (in)             15 RETURN_VALUE

The second case, evaluates to True not in [False, True], which is False clearly:

>>> x = lambda: not(True) in [False, True]>>> dis.dis(x)  1           0 LOAD_GLOBAL              0 (True)              3 LOAD_GLOBAL              1 (False)              6 LOAD_GLOBAL              0 (True)              9 BUILD_LIST               2             12 COMPARE_OP               7 (not in)             15 RETURN_VALUE        >>> 

What you wanted to express instead was (not(True)) in [False, True], which as expected is True, and you can see why:

>>> x = lambda: (not(True)) in [False, True]>>> dis.dis(x)  1           0 LOAD_GLOBAL              0 (True)              3 UNARY_NOT                         4 LOAD_GLOBAL              1 (False)              7 LOAD_GLOBAL              0 (True)             10 BUILD_LIST               2             13 COMPARE_OP               6 (in)             16 RETURN_VALUE        


Operator precedence. in binds more tightly than not, so your expression is equivalent to not((True) in [False, True]).