GICT knowledge base
Python Logical Operators: and, or, not and Short-Circuiting
Published
Python’s logical operators are and, or and not. They test truth values, but only not always returns a Boolean. and and or return one of their operands, and can skip evaluating the other operand.
The following self-contained examples were executed with Python 3.12.14. They use sample values rather than login or permission checks.
Read the Boolean truth table
With Boolean operands, and is true when both inputs are true; or is true when at least one is true. not reverses the truth value.
| a | b | a and b | a or b |
|---|---|---|---|
| False | False | False | False |
| False | True | False | True |
| True | False | False | True |
| True | True | True | True |
rows = []
for a in [False, True]:
for b in [False, True]:
rows.append((a, b, a and b, a or b))
assert rows == [
(False, False, False, False),
(False, True, False, True),
(True, False, False, True),
(True, True, True, True),
]
assert (not True) is False
print(rows)
Understand truthiness and returned operands
Common false values include None, numeric zero, and empty strings or containers. Non-empty strings are truthy even if their text says "False". Custom classes can define their own truth behavior. Use bool(value) when you specifically need a Boolean result.
a and b returns a if it is falsey, otherwise b. a or b returns a if it is truthy, otherwise b. A chain of alternatives returns the last operand if all earlier operands are falsey.
assert ("web" and 443) == 443
assert ([] and "unused") == []
assert ("web" or "fallback") == "web"
assert ("" or 0 or None) is None
assert bool("False") is True
assert (not []) is True
assert all(not value for value in [None, 0, 0.0, "", [], {}, set()])
print(bool("False"))
Use short-circuit evaluation deliberately
The second operand is evaluated only if needed. This can guard a calculation, but should not hide important side effects. Here the function records whether it was called, so the skipped calls are observable rather than assumed.
calls = []
def record():
calls.append("called")
return "result"
assert (False and record()) is False
assert (True or record()) is True
assert calls == []
assert (True and record()) == "result"
assert calls == ["called"]
denominator = 0
safe_to_divide = denominator != 0 and 10 / denominator > 2
assert safe_to_divide is False
print(calls)
Parentheses can change the answer
Comparisons bind more tightly than not, which binds more tightly than and, then or. Precedence determines grouping; it does not make every not expression execute before all other work. Use parentheses to show the intended grouping, not to disguise a change in logic.
x = 8
y = 12
first = not (x > 5) and (y < 10)
second = not ((x > 5) and (y < 10))
assert first is False
assert second is True
ready = True
paused = False
urgent = True
assert (ready and not paused or urgent) is True
assert ((ready and not paused) or urgent) is True
print(first, second)
Preserve meaningful zero and False values
value or default replaces every falsey value, not only missing values. If zero means no retries, silently replacing it with three retries changes the setting. Compare with None when that is your missing-value marker.
def retries_or_default(value):
return 3 if value is None else value
assert retries_or_default(None) == 3
assert retries_or_default(0) == 0
assert retries_or_default(5) == 5
assert (0 or 3) == 3
print(retries_or_default(0))
Write each comparison, or use membership
state == "ready" or "queued" does not compare state twice. The non-empty string makes the condition truthy when the first comparison is false. For alternatives, use membership; for a numeric interval, use a chained comparison or two comparisons joined with and.
state = "failed"
incorrect = state == "ready" or "queued"
correct = state in {"ready", "queued"}
assert incorrect == "queued"
assert bool(incorrect) is True
assert correct is False
within = [2 <= hour < 5 for hour in [1, 2, 4, 5]]
assert within == [False, True, True, False]
print(correct, within)
Use and/or, not bitwise &/|, for ordinary Boolean conditions. Libraries that overload operators, such as array libraries, have their own rules. Also avoid treating the presence of an email address, username or API-key string as proof of authentication.
Verification: All six blocks and their assertions ran independently, including short-circuit call counts. References: Boolean expression rules and truth-value testing. Continue with if, elif and else.
Related guides
How to Deploy a FastAPI App with Gunicorn and Nginx
Deploy FastAPI behind Nginx with Gunicorn and systemd. Separate application packages, check HTTPS and verify worker replacement and application health.
PythonLearn How to Modify Python Dictionary Values Easily
Learn how to modify Python dictionary values effectively with various methods, including direct assignment, update(), and comprehensions, along with common mistakes to...
PythonPython Set Copy Tutorial: Avoid Common Mistakes and Data Errors
Learn how to copy sets in Python safely and efficiently while avoiding common mistakes. Explore methods like copy(), set(), and deepcopy().
PythonDifferent Methods to Loop Through Sets in Python (Beginner-Friendly Guide)
Learn diverse methods to loop through sets in Python, including practical examples and use cases, ideal for beginners looking to master set operations.
