BitBootcampBitBootcamp ← all explainers 🔄 Review ⚙ Settings

PY-01-005-P · Primer — Booleans & Comparisons

The idea in one sentence

A Boolean is a value that is either True or False, and it's the answer your program gets whenever it asks a question — is this bigger than that? are both of these true? — which is exactly how code decides what to do next.

Why it exists

Every interesting program has to make choices: show the dashboard if the user is logged in, apply the discount if the cart is over $50, retry if the request failed. To make a choice, the computer needs a clean yes-or-no answer, and that answer is a Boolean — Python's bool type, which has exactly two values, True and False. Comparisons (<, ==, !=, and friends) are the questions that produce those Booleans; logical operators (and, or, not) are how you combine several questions into one; and truthiness is Python's rule for reading a yes/no answer out of any value at all — not just real Booleans. These four ideas exist together because a program is, at heart, a long chain of decisions, and this is the vocabulary those decisions are written in. Learn this vocabulary and if statements, loops, and filters all suddenly read like plain English.

How it works

A comparison asks a question and hands back a bool: < <= > >= for ordering, == for "equal to," and != for "not equal to" — note == (a question) is a completely different thing from = (assignment). You combine answers with the three logical operators: and is True only when both sides are true, or is True when either side is true, and not flips a Boolean to its opposite. Python is also lazy on purpose — this is short-circuiting: A and B never even looks at B if A is already False (the answer can't change), and A or B skips B if A is already True. Finally, truthiness lets you test any value as if it were a Boolean: empty things (0, "", [], {}, None) count as False, and everything else counts as True, which is why if my_list: reads as "if the list has anything in it." You can see all of this — including that comparisons really do produce bools — at a glance:

age = 20
is_member = True

print(age >= 18)                 # True   -> a comparison hands back a bool
print(is_member and age >= 18)   # True   -> both sides true
print(type(age >= 18))           # <class 'bool'>

name = ""                        # an empty string is "falsy"
print(bool(name))                # False
print(name or "guest")           # guest  -> or returns the first truthy value

x = 7
print(0 < x < 10)                # True   -> Python chains comparisons like math

Notice the last line: Python lets you write 0 < x < 10 exactly the way you'd write it in math class, and it means "x is between 0 and 10."

The one gotcha

and and or don't always return True or False — they return one of the actual operands, and that's a feature you'll use every day. Because of short-circuiting, or returns the first truthy value it finds and and returns the first falsy value (or the last value if none is falsy). So "" or "guest" isn't True — it's the string "guest", which is why name or "guest" is the classic one-line way to supply a default. The same mechanic bites beginners when they lean on truthiness carelessly: if score: is False when score is 0, so a perfectly valid score of zero gets silently skipped as if it were missing. When you genuinely mean "does this value exist?" and not "is this value non-empty," test explicitly with if score is not None:. And keep == and is straight — == asks "are these equal in value?" (almost always what you want), while is asks "are these the exact same object?" (reserve it for None, True, False).

See it — how a value becomes a yes/no decision

flowchart TD
    A["An expression<br/>to evaluate"] --> B{"Is it a<br/>comparison?"}
    B -->|"Yes: < == != etc."| C["Returns a real<br/>bool: True/False"]
    B -->|"No: any value"| D{"Is it empty?<br/>0 '' [] {} None"}
    D -->|"Yes (falsy)"| E["Treated as False"]
    D -->|"No (truthy)"| F["Treated as True"]
    C --> G{"Combine with<br/>and / or / not?"}
    E --> G
    F --> G
    G -->|"and: stop at<br/>first falsy"| H["Short-circuits;<br/>skips the rest"]
    G -->|"or: stop at<br/>first truthy"| H
    G -->|"no combine"| I["Use value as<br/>the decision"]
    H --> I

The one-line takeaway

Comparisons produce True/False, and/or/not combine them (and short-circuit, returning an actual operand), and every value has a truthiness — but test is not None when you mean "exists," because 0 and "" are falsy.

Where you'll meet it

You'll meet Booleans in the very next thing you learn — the if statement — because the condition after if is nothing but a Boolean question. You'll write if user and user.is_active: and lean on short-circuiting so the second half never runs when user is None. You'll use name or "guest" to fill in defaults, while queue: to loop until a list empties, and [n for n in nums if n > 0] to filter with a comparison. The if score:-skips-zero trap will find you the first time a real zero disappears from your results, and knowing to reach for is not None in that moment is a genuine mark of fluency. From guarding against bad input to controlling every loop and branch, almost every decision your programs make from here on is a Boolean — this small handful of operators is the grammar of choosing.

Named concepts: True/False and bool, comparison operators, and/or/not and short-circuiting, truthiness of values