Python’s not operator returns True if the single operand evaluates to False, and returns False if it evaluates to True. Thus, it logically negates the implicit or explicit Boolean value of the operand.
As you read through the article, you can also watch my video for supporting explanations:
Python Not Operator on Boolean
You can apply the not operator to a Boolean value and Python invert the Boolean operand. Thus, the expression not False becomes True and not True becomes False.
| Operand: A | not A | 
|---|---|
| False | True | 
| True | False | 
You can see those examples in the following script:
>>> not False True >>> not True False
Python Not Operator on Integer
You can apply the not operator to an integer value. Python internally converts the integer value to a Boolean value, i.e., all non-zero integers will be converted to True and integer 0 to False. The resulting Boolean is then inverted by the not operator. For example, the expression not 1 becomes False and not 0 becomes True.
| Operand: A | not A | 
|---|---|
| 1 | False | 
| 99 | False | 
| -99 | False | 
| 0 | True | 
All integers except 0 are internally converted to a True Boolean value. Thus, the integers 1, 99, and even -99 lead to the calculation of not True which evaluates to False.
You can see those examples in the following script:
>>> not 1 False >>> not 99 False >>> not -99 False >>> not 0 True
Python Not Operator Overloading
Interestingly, you can also apply the logical NOT operator on arbitrary Python objects. The base idea is the “truthiness” of Python objects, i.e., every Python object has an associated Boolean value as determined by the __bool__() magic method.
In the following code, you create a custom class called My_Obj and use the “not” operator on instances of this class. You explicitly define the __bool__() method to customize the behavior of the not operator on your custom classes.
class My_Obj:
    def __init__(self, number):
        self.number = number
    def __bool__(self):
        return bool(self.number)
my_0 = My_Obj(0)
my_1 = My_Obj(1)
my_99 = My_Obj(99)
print('not', my_0.number, '=', not my_0)
print('not', my_1.number, '=', not my_1)
print('not', my_99.number, '=', not my_99)
The outputs are:
not 0 = True not 1 = False not 99 = False
If you hadn’t overridden the __bool__ magic method, Python would assume all objects of the custom objects to be True, so the results would be False for all three objects.
Python Not Operator on Lists
You can apply the not operator on arbitrary objects including lists. Every list object has an associated Boolean value as determined by the bool(list) method—all lists evaluate to True except the empty list. If you apply the not operator on a non-empty list, Python always returns False. Only an empty list will be evaluated to True under the not operator. That’s why you often see the expression not list in an if statement to ensure that the list is non-empty in the else body.
l_1 = [1, 2, 3]
l_2 = []
if not l_1:
    print(l_1, 'is empty')
else:
    print(l_1, 'is non-empty')
if not l_2:
    print(l_2, 'is empty')
else:
    print(l_2, 'is non-empty')
The output of this code snippet is:
[1, 2, 3] is non-empty [] is empty
Python Not Operator on Strings
Apply the not operator on strings to check if a string is empty. Every string has an associated Boolean value as determined by bool(string) and all strings evaluate to True except the empty string. If you apply the not operator on a non-empty string, Python returns False. If you apply it to an empty string, Python returns True. That’s why you often see the expression not string in an if statement to ensure that the string is empty in the if body.
s_1 = 'finxter'
s_2 = ''
if not s_1:
    print('string s_1', s_1, 'is empty')
else:
    print('string s_1', s_1, 'is non-empty')
if not s_2:
    print('string s_2', s_2, 'is empty')
else:
    print('string s_2', s_2, 'is non-empty')
The output of this code snippet is:
string s_1 finxter is non-empty string s_2 is empty
Python Not Operator Precedence
Python evaluates not before any other logical operand such as and or or. Thus, the expression not x and y will evaluate (not x) and y and not not (x and y).
The following example shows that the first two interpretations of the operator precedence are the same whereas the third is different. Thus, the not operator takes precedence before the and operator.
>>> not True and False False >>> (not True) and False False >>> not (True and False) True
As the and operator takes precedence before the or operator, the not operator takes precedence before the or operator as well. Here’s the proof:
>>> not False or True True >>> (not False) or True True >>> not (False or True) False
The first two cases generate the same results because they are the same—the not operator is evaluated first.
Logical Operators
Logical operators are shortcuts to perform Boolean comparisons, but can be used on integers and other objects as well.
| Operator | Description | Example | 
|---|---|---|
| and | Returns Trueif both operands areTrue, andFalseotherwise. | (True and True) == True | 
| or | Returns Trueif at least one of the two operands isTrue, andFalseotherwise. | (False or True) == True | 
| not | Returns Trueif the single operand isFalse, andFalseotherwise. | (not True) == False | 
