If I do this:

>>> False in [False, True] True

That returns `True`

. Simply because `False`

is in the list.

But if I do:

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

That returns `False`

. Whereas `not(True)`

is equal to `False`

:

>>> not(True) False

Why?

Skip to content
# python – Why does “not(True) in [False, True]” return False?

## The Question :

*483 people think this question is useful*
*The Question Comments :*
## The Answer 1

*733 people think this answer is useful*

## The Answer 2

*76 people think this answer is useful*
## The Answer 3

*36 people think this answer is useful*
## The Answer 4

*33 people think this answer is useful*
## The Answer 5

*14 people think this answer is useful*
## The Answer 6

*13 people think this answer is useful*

## The Answer 7

*6 people think this answer is useful*
## The Answer 8

*6 people think this answer is useful*

2021-01-13

If I do this:

>>> False in [False, True] True

That returns `True`

. Simply because `False`

is in the list.

But if I do:

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

That returns `False`

. Whereas `not(True)`

is equal to `False`

:

>>> not(True) False

Why?

- related stackoverflow.com/questions/31354429/…
- your parentheses are confusing in
`not(True) in [False, True]`

**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])`

.

It’s all about operator precedence (`in`

is stronger than `not`

). But it can be easily corrected by adding parentheses at the right place:

(not(True)) in [False, True] # prints true

writing:

not(True) in [False, True]

is the same like:

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

which looks if `True`

is in the list and returns the “not” of the result.

It is evaluating as `not True in [False, True]`

, which returns `False`

because `True`

is in `[False, True]`

If you try

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

You get the expected result.

Alongside the other answers that mentioned the precedence of `not`

is lower than `in`

, actually your statement is equivalent to :

not (True in [False, True])

But note that if you don’t separate your condition from the other ones, python will use 2 roles (`precedence`

or `chaining`

) in order to separate that, and in this case python used precedence. Also, note that if you want to separate a condition you need to put all the condition in parenthesis not just the object or value :

(not True) in [False, True]

But as mentioned, there is another modification by python on operators that is **chaining**:

Based on python *documentation* :

Note that comparisons, membership tests, and identity tests, all have the same precedence and have a left-to-right

chainingfeature as described in the Comparisons section.

For example the result of following statement is `False`

:

>>> True == False in [False, True] False

Because python will chain the statements like following :

(True == False) and (False in [False, True])

Which exactly is `False and True`

that is `False`

.

You can assume that the central object will be shared between 2 operations and other objects (False in this case).

And note that its also true for all Comparisons, including membership tests and identity tests operations which are following operands :

in, not in, is, is not, <, <=, >, >=, !=, ==

Example :

>>> 1 in [1,2] == True False

Another famous example is number range :

7<x<20

which is equal to :

7<x and x<20

Let’s see it as a collection containment checking operation: `[False, True]`

is a list containing some elements.

The expression `True in [False, True]`

returns `True`

, as `True`

is an element contained in the list.

Therefore, `not True in [False, True]`

gives the “boolean opposite”, `not`

result of the above expression (without any parentheses to preserve precedence, as `in`

has greater precedence than `not`

operator).
Therefore, `not True`

will result `False`

.

On the other hand, `(not True) in [False, True]`

, is equal to `False in [False, True]`

, which is `True`

(`False`

is contained in the list).

To clarify on some of the other answers, adding parentheses *after* a unary operator does not change its precedence. `not(True)`

does not make `not`

bind more tightly to `True`

. It’s just a redundant set of parentheses around `True`

. It’s much the same as `(True) in [True, False]`

. The parentheses don’t do anything. If you want the binding to be more tight, you have to put the parentheses around the whole expression, meaning both the operator and the operand, i.e., `(not True) in [True, False]`

.

To see this another way, consider

>>> -2**2 -4

`**`

binds more tightly than `-`

, which is why you get the negative of two squared, not the square of negative two (which would be positive four).

What if you did want the square of negative two? Obviously, you’d add parentheses:

>>> (-2)**2 4

However, it’s not reasonable to expect the following to give `4`

>>> -(2)**2 -4

because `-(2)`

is the same as `-2`

. The parentheses do absolutely nothing. `not(True)`

is exactly the same.