Why does notTrue in False, True return False?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Python, expressions and their expected outputs can sometimes be counterintuitive to those new to the language or programming in general. A particularly interesting example is the expression not(True) in [False, True]
. Unexpectedly, it returns False
. Understanding why this happens requires a dive into operator precedence and logical evaluation in Python.
Understanding Operator Precedence
Operator precedence determines the order in which operators are evaluated. In Python, just like in many other languages, some operations are performed before others unless overridden by parentheses. Below is a simplified list of common operators sorted by their precedence, from highest to lowest:
- Parentheses
() - Exponentiation
** - Unary operations like
not,+,- - Multiplicative operators like
*,/,% - Additive operators like
+,- - Relational operators like
==,!=,>,< - Logical AND
and - Logical OR
or - Membership tests
in,not in
From this table, it is clear that the not
operator has higher precedence than the in
operator.
Step-By-Step Evaluation of not(True) in [False, True]
Now, let's break down the evaluation of not(True) in [False, True]
:
- Apply
nottoTrue:
Thenotoperator negates the BooleanTrue, transforming it toFalse.
Intermediate result:False in [False, True] - Evaluate Membership Test
in:
The expression now checks if the result ofnot True, which isFalse, exists in the list[False, True]. SinceFalseis indeed present in the list, the evaluation returnsTrue.
The reason the original expression returns False
is because many assume not
negates the entire expression following it due to the lack of parentheses, which it doesn't. not
here only negates the operand immediately after it, i.e., True
, and not the result of the entire membership test True in [False, True]
.
Correct Usage with Parentheses
If the intention is to negate the entire membership expression, parentheses must be used to adjust the precedence:
- **
not Truevsnot (True)**: Both returnFalseasnotdirectly applies toTrue. - **
False in [False, True]**: Direct membership test, returnsTrue. - **
True not in [False, True]**:Trueis in the list, but thenot inchanges the context, returningFalse.

