Python Logical Operators: and, or, not Explained

Python logical operators combine conditions and return a result based on truthiness, not just true and false values. Use and when both conditions must be true, or when either condition can be true, and not when you want to flip a condition. This article shows how they work, why short-circuiting matters, and where beginners often get confused.

Difficulty: Beginner

Helpful to know first: basic variables, comparison operators like == and >, and how if statements use conditions.

How Python Logical Operators Work

Python has three logical operators: and, or, and not. They are used to build larger conditions from smaller ones, such as checking whether a number is in a range or whether a user is logged in and has permission.

Unlike many languages, Python does not always force these operators to return only True or False. Instead, and and or return one of their operands, and that operand is chosen using truthiness. That is why these operators are useful both in conditions and in normal expressions.

Python
age = 20
has_id = True

if age >= 18 and has_id:
    print("Allowed in")
else:
    print("Not allowed")
# Output: Allowed in

In this example, both parts of the condition must be true. The first part checks the age, and the second part checks the ID flag. Because both are true, the whole if condition is true.

Working With and, or, and not

The three operators follow simple rules:

  • and returns the first false value it finds, or the last value if all are true.
  • or returns the first true value it finds, or the last value if all are false.
  • not always returns a Boolean value, True or False.

This makes the operators useful for conditions, defaults, and simple checks. The examples below move from basic Boolean logic to realistic Python patterns.

Using and to require two conditions

Use and when both conditions must be true. A common example is a range check.

Python
temperature = 22

if 18 <= temperature and temperature <= 25:
    print("Comfortable")
else:
    print("Not comfortable")
# Output: Comfortable

This reads naturally: the temperature must be at least 18 and at most 25. The same pattern appears in validation code, permission checks, and loops that filter data.

Using or to accept either condition

Use or when one true condition is enough. This is common when you want to accept multiple valid inputs.

Python
is_weekend = False
is_holiday = True

if is_weekend or is_holiday:
    print("No school")
else:
    print("School day")
# Output: No school

Only one side needs to be true. Here, is_holiday is true, so the full expression is true even though is_weekend is false.

Using not to flip a condition

Use not when you want the opposite meaning of a condition. This is useful for readable conditions such as “if not empty” or “if not logged in.”

Python
is_empty = False

if not is_empty:
    print("There is data")
else:
    print("No data")
# Output: There is data

The not operator changes False to True and True to False. It always produces a Boolean result.

Using logical operators with truthy and falsy values

Python lets many values act as true or false in a condition. Empty strings, zero, empty containers, and None are falsy. Non-empty values are truthy.

Python
name = "Ada"
nickname = ""

print(name and nickname)
print(name or "Anonymous")
# Output:
# 
# Ada

The first line returns the empty string because and stops at the first falsy value. The second line returns name because it is truthy, so or stops immediately.

How Python Decides What Counts as True or False

Python checks an object's truth value when it evaluates logical operators and if statements. Most built-in types follow simple rules. Zero is false, empty sequences and collections are false, and None is false. Most other values are true.

This truthiness rule matters because logical operators do not require operands to be actual Boolean values. A list, string, number, or object can all be used in a logical expression.

Python
print(bool(0))
print(bool(3))
print(bool(""))
print(bool("Python"))
# Output:
# False
# True
# False
# True

Knowing this helps you read expressions like items and items[0] or user_input or default_value. The operator uses truthiness to decide what to return.

Short-Circuiting: Why Python Sometimes Stops Early

Python does not always evaluate both sides of a logical expression. This behavior is called short-circuiting. It matters because it can save work and prevent errors.

With and, Python stops as soon as it finds a false value. With or, Python stops as soon as it finds a true value.

Python
def left():
    print("left")
    return False

def right():
    print("right")
    return True

print(left() and right())
# Output:
# left
# False

right() is never called here because left() already returned False. That is why short-circuiting is useful for guarding code that might fail.

Python
user = None

if user and user["name"] == "Ada":
    print("Matched")
else:
    print("No match")
# Output: No match

Because user is None, Python never tries to access user["name"]. That prevents a TypeError and makes the check safe.

Operator Precedence: Why Some Expressions Need Parentheses

Python evaluates not before and, and and before or. This order often surprises beginners.

Python
print(not True and False)
print((not True) and False)
# Output:
# False
# False

In this case the results match, but the grouping is still important. Without parentheses, Python reads the first line as (not True) and False.

Here is a case where precedence changes the result:

Python
print(True or False and False)
print((True or False) and False)
# Output:
# True
# False

Python reads the first line as True or (False and False), not as (True or False) and False. Parentheses make the meaning obvious and prevent logic bugs.

Predict the Output

Short-circuiting with and

What does this print?

Python
def check(value):
    print(value)
    return value > 0

print(check(-1) and check(2))
Show answer

Answer: It prints -1 and then False.

Why: check(-1) prints -1 and returns False because -1 > 0 is false. Since and stops at the first false value, Python never calls check(2).

Terminal
# Output:
# -1
# False

Returning values with or

What does this print?

Python
name = ""
display_name = name or "Guest"
print(display_name)
Show answer

Answer: It prints Guest.

Why: The empty string is falsy, so or returns the right-hand value. This pattern is common for fallbacks and defaults.

Terminal
# Output:
# Guest

Common Mistakes With Python Logical Operators

Using and when you meant or

Beginners often write a condition that is too strict. They want to allow either option, but they accidentally require both.

Problem: This condition can never be true for a single number because a value cannot be less than 5 and greater than 10 at the same time.

Python
number = 7

if number < 5 and number > 10:
    print("In range")

Fix: Use or for either side, or use a chained comparison for a real range check.

Python
number = 7

if number < 5 or number > 10:
    print("Outside range")
else:
    print("Inside range")
# Output: Inside range

The fixed version matches the actual meaning of the check.

Forgetting that not needs one value, not two

The not operator flips one condition. It does not compare two values.

Problem: This code tries to use not like an equality test, which is not valid Python syntax.

Python
x = 3
y = 4

if x not y:
    print("Different")

Fix: Use != to test inequality, or not with a full comparison.

Python
x = 3
y = 4

if x != y:
    print("Different")
# Output: Different

The corrected version uses the comparison operator designed for inequality.

Relying on truthiness when you need an exact Boolean

Sometimes a value such as 0 or an empty string is valid data, not a missing value. If you use or to supply a default, you may replace a real value by mistake.

Problem: This code treats 0 as if it were missing, so it chooses the default value instead of keeping the real input.

Python
quantity = 0
result = quantity or 10
print(result)

Fix: Check explicitly for None when zero is a meaningful value.

Python
quantity = 0
result = 10 if quantity is None else quantity
print(result)
# Output: 0

The corrected version keeps zero because it checks for missing data instead of falsy data.

Find the Bug

A teammate wrote this code to print a safe username. It looks reasonable, but it has a subtle bug. Find it.

Python
user = {"name": ""}
name = user.get("name") or "Guest"
print(name)
Show answer

What is wrong: The code treats an empty string as missing data. If an empty string is a valid username, the fallback to "Guest" changes the real value.

Why it matters: or uses truthiness, so it replaces any falsy value, including "", 0, and False. That is correct for many defaults, but not for every input field.

Fixed code: Check specifically for None if missing data is the only case that should use the default.

Python
user = {"name": ""}
name = "Guest" if user.get("name") is None else user.get("name")
print(name)
# Output:
# 

The fix works because it preserves empty strings and only replaces a missing value.

When to Use Logical Operators and When to Use Something Else

Logical operators are the right tool when you need a Boolean decision or a truthy/falsy choice. They are not the best tool for every kind of test.

NeedUse thisWhy
Both conditions must be trueandIt combines two checks into one decision.
Either condition may be trueorIt accepts the first true value.
Flip a conditionnotIt changes true to false and false to true.
Test exact equality or inequality==, !=These compare values directly instead of using truthiness.
Check a rangeChained comparison like 0 < x < 10It is clearer than combining two comparisons with and.

A common mistake is to force logical operators into jobs that comparison operators already do better. For example, use x == 5 to check whether x equals 5. Do not write x and 5 if you really mean equality.

Predict the Output

Comparing and with returned values

What does this print?

Python
print("cat" and "dog")
print("" or "fallback")
Show answer

Answer: It prints dog and then fallback.

Why: and returns the second operand when the first one is truthy. or returns the second operand when the first one is falsy. The result is not always a Boolean.

Terminal
# Output:
# dog
# fallback

Try It Yourself

Write a program that asks Python to decide whether a number is inside the inclusive range from 10 to 20.

  • Set a variable named number to 15.
  • Use one if statement with logical operators.
  • Print "Inside" if the number is between 10 and 20, inclusive.
  • Otherwise print "Outside".

Expected output:

Python
Inside

Hint: The condition should use two comparisons joined by and.

Show solution
Python
number = 15

if 10 <= number and number <= 20:
    print("Inside")
else:
    print("Outside")

Summary

  • and needs both sides to be truthy to continue.
  • or needs only one truthy side.
  • not flips a condition and returns a Boolean result.
  • Python uses truthiness, so operands do not need to be actual Booleans.
  • and and or short-circuit, so Python may skip the right-hand side.
  • Use parentheses when precedence could make the meaning unclear.

Next, learn Python comparison operators so you can build the individual conditions that logical operators combine.