Python not Operator: The Complete Guide to Logical Negation

Kimberly FesselKimberly Fessel

Python Not Operator explained

Python’s logical operators are totally lame... not!

Now that I’ve gotten that lame 90s joke out of my system, let’s talk about not, a powerful for negating logical expressions in Python. The not operator brings you a topsy-turvy view of the world: True becomes False, False becomes True, and with it, your favorite operators (is, in, etc.) behave like it’s “Opposite Day.” You’ll see not throughout Python code, so it’s worth paying attention to.

This article focuses on the Python not operator. You’ll learn what it is, how to add it to , and how it compares to similar constructs like != and ~. It’s a foundational concept with plenty of intricacies, so let’s get going.

The not Keyword as a Boolean Operator

The not keyword is a logical operator in Python. It gives the opposite : True becomes False, and False becomes True:

python
print(not True) # Expected result:# False

The not operator returns a Boolean value always. It often helps simplify logic so that you can write cleaner code for conditional statements and . For instance, this if statement prints a denied entry message if the user does not have permission:

python
if not user_has_permission:     print("Access denied.")

The user_has_permission variable will either be True or False, and not negates the Boolean variable.

not Operator in Python: Truthiness

While the not operator frequently appears with Boolean expressions, it can also show up when evaluating in Python. Python classifies values as “truthy” or “falsy” to extend the concept of True and False beyond traditional Booleans. Common examples of “falsy” values include:

  • False

  • None

  • 0, 0.0, or 0j

  • [], {}, (), or set()

  • "" (empty string)

  • range(0)

Just about everything else is truthy.

Use the not operator to catch empty lists or strings, zero-valued integers or floats, nulls (None), or other falsy values. Here’s an example:

python
if not list_of_values:     raise ValueError("The list cannot be empty.")

Note that Python evaluates if not list_of_values as True when list_of_values is empty because empty lists are falsy. This syntax is generally preferred over checking the length of a list (if len(list_of_values) == 0) for readability and to be more Pythonic.

Using the not Operator in Statements

You’ve already seen a few examples of not in conditional statements. This is the primary place to use the not logical operator, so let’s dive even deeper and explore not with while loops as well.

Conditional Statements (if Statements)

Conditional statements control program flow by executing a portion of code only when a particular statement evaluates to True. Classically, Python uses the if, elif, else keywords to establish logical flow, but more recent versions of Python (3.10+) now allow match for pattern-based branching. Incorporate the not operator into these flows to negate statements.

In the following Python snippet, the if conditional checks the truthiness of the user_input variable, and the elif conditional determines if the input is numeric. Once the code verifies a valid input, it safely converts to an integer and adds the inputted amount to a running total.

python
if not user_input:     print("No input provided.")elif not user_input.isdigit():    print("Input must be numeric.")else:     number = int(user_input)     total = total + number

The match statement allows you to compare against multiple patterns in a defined order. In the same spirit as the CASE, match evaluates each case sequentially and executes at the first matching branch. You typically won’t use the not operator within the case patterns themselves; instead, you handle edge cases like empty or invalid values with before the match block begins:

python
text = ""if not text:     print("No command provided.")elif not text.isalpha():     print("Invalid command format.")else:     match text.lower():         case "start":             print("Process starting.")             case "stop":             print("Process stopping.")         case "pause":             print("Process pausing.")         case _:             print("Unknown command.") # Expected result:# No command provided.

while Loops

In Python, while loops continuously execute code until a condition becomes false. Truthiness comes in particularly handy here, and you’ll typically add not to loop conditions to check against flags, collections, and search conditions. The not operator helps the loop syntax read more like natural language, such as “while not finished” or “while not empty,” and it often appears in real-world problems to wait until something exists.

The queue in code below begins as an empty list, not queue evaluates to True, so the loop runs. Inside the loop, task_1 adds to the queue, making the list non-empty (truthy). not queue becomes False, causing the loop to stop.

python
queue = [] while not queue:     print("Waiting for tasks…")         queue.append("task_1") # Expected result:# Waiting for tasks…

Combining not with Other Logical Operators and Complex Conditions

As you add not to your Python code, you’ll eventually want to pair it with other operators like and, or, is, or in to build more complex statements. The not operator works well alongside these other Python constructs, but there are a few important nuances to keep in mind.

Logical Operators: and, or

The logical operators and and or allow you to combine multiple conditions. and requires both conditions to be True, while or requires at least one condition to be True. Here’s an example of and and or with Boolean values:

python
print(True and False)print(True or False) # Expected result:# False# True

Like you saw for conditionals, the not operator negates the truth value of an expression. You can use it to negate individual expressions or grouped conditions:

python
print((not True) and False) print(not (True and False)) # Expected result:# False# True

Operator Precedence

dictates the order Python evaluates operators in an expression. You may have heard of for arithmetic expressions. This is the same idea, just extended to all operators in Python.

For logical operators:

  • not has higher precedence than and

  • and has higher precedence than or

This is what you can expect in Python:

python
print(not True and False) print(not True or False) print(True and False or True) print(True or False and False) # Expected result:# False# False# True# True

(==, !=, <, >, and so on) have higher precedence than logical operators. Python evaluates them before not, and, or or. This means that Python interprets expressions like not x > 4 as not (x > 4), with the comparison happening first.

python
x = 8print(not x > 4) #not (x > 4) → not True → False # Expected result:# False

You can avoid confusion in this code by switching to x ≤ 4. For other cases, add parentheses. Parentheses override any default precedence. They’re always evaluated from inside out and should be used to make intent explicit and improve readability.

Compound Forms: not in and is not

The not operator naturally complements two related operators to form not in and is not. These are compound operators that make Python code easier to understand and are generally preferred over negating statements involving in or is (e.g. not (x in y) or not (x is y)).

The not in gives you the ability to cleanly check if an item is absent from a collection (string, list, dictionary, set, etc.). It’s the opposite of the in operator, and here’s an example:

python
dogs_in_park = ["Buddy", "Charlie", "Lola", "Tucker"] dog = "Sandy" if dog not in dogs_in_park:     print(f"{dog} is not at the dog park.") # Expected result:# Sandy is not at the dog park.

In Python, is not is an identity operator. It determines if two variables are not the same object in memory, and you’ll often use it to check against None.

python
if x is not None:     processed_value = str(x).upper()else:     raise ValueError("x cannot be None")

Be sure not to confuse the inequality operator != with the identity operator is not. Use != to compare values and reserve is not to test identity. For instance:

python
a = [1, 2, 3]b = [1, 2, 3] print(a != b)print(a is not b) # Expected result:# False# True

The a and b lists have the same contents, so a != b gives False; however, a and b are stored at different memory locations, so a is not b returns True.

not vs Similar Operators Comparison Table

Operator

Operator Type

What It Does

Applies To

Common Use Case

Example

not

Logical

Reverses truthiness of an expression

Any expression (truthy/falsy values)

Checking emptiness or negating conditions

if not items:

not in

Membership

Checks a value is not contained in a collection

Strings, lists, sets, dicts

Excluding values

"g" not in "cat"

is not

Identity

Checks whether two objects are not the same object

Objects, None

None checks, identity comparisons

x is not None

!=

Comparison

Checks whether two objects are not equal

Numbers, strings, comparable objects

Value inequality checks

x != 10

~

Bitwise

Flips all bits of an integer; in pandas/NumPy, flips Boolean values elementwise

Integers; Boolean arrays (pandas/NumPy)

Low-level bit manipulation; negating masks in pandas/NumPy

~5 or ~df["col"].isna()

Best Practices and Common Pitfalls

You’ve already seen a few gotchas in this article (misunderstanding operator precedence, confusing != with is not), and here are a couple more. When using the not operator, make sure not to make these mistakes.

Creating Double Negatives in Boolean Logic

The not operator gives you a powerful new way to write conditionals and loops, but be sure not to overuse it. Try to simplify the conditions as much as possible. Like the English language, that means avoiding double negatives.

Both of the following conditional statements are logically equivalent, but the second one is preferred since it’s clearly easier to understand:

python
x = 2 if not x != 1:     print("x is equal to 1") if x == 1:    print("x is equal to 1")

Confusing not (logical operator) with ~ (bitwise operator)

If you’re confusing not for ~, chances are you’re using the pandas or NumPy library. In those libraries, ~ works elementwise on series, dataframes, and arrays, oftentimes used to invert each entry of a Boolean mask. Here’s a snippet that determines if each department value is missing, then flips those Booleans with ~:

python
~df["department"].isna()

Say you attempt to use the not operator with a mask instead:

python
not df["department"].isna()

not cannot operate on a pandas Series because a Series does not reduce to a single Boolean value. For example, df[].isna() returns a Series of True and False values, which raises a ValueError when used with not:

ValueError: The truth of a Series is ambiguous.

However, do continue to use the not operator with single-valued Booleans or when checking the truthiness of a single value:

python
if not df.empty:     print("The dataframe contains rows")

Wrapping Up

In Python, not is a logical operator to help you flip Booleans and negate truthiness. You’ll find it in conditional statements, paired with other logical operators (and, or), and in compound operators (not in, is not). To keep it straight from other negation operators, remember that not works logically, for single Boolean values or single expressions.

Take your not knowledge to the next level by interacting with the AI Tutor. Here’s a prompt to get you started:

Join the Community

roadmap.sh is the 6th most starred project on GitHub and is visited by hundreds of thousands of developers every month.

Rank  out of 28M!

355K

GitHub Stars

Star us on GitHub
Help us reach #1

+90kevery month

+2.8M

Registered Users

Register yourself
Commit to your growth

+2kevery month

48K

Discord Members

Join on Discord
Join the community

RoadmapsGuidesFAQsYouTube

roadmap.shby@nilbuild

Community created roadmaps, best practices, projects, articles, resources and journeys to help you choose your path and grow in your career.

© roadmap.sh·Terms·Privacy·

ThewNewStack

The top DevOps resource for Kubernetes, cloud-native computing, and large-scale development and deployment.