Beginner14 min

Booleans, comparisons, and truthiness

True and False, the truthiness of every type, is vs ==, short-circuit logic, and any/all.

Why this matters in AI / ML / GenAI

Filtering predictions, guarding empty batches, and checking optional config all depend on truthiness. The subtle bug is that a valid score of 0.0 is falsy, so `if score:` silently drops it.

Truthiness

Every object is either truthy or falsy in a boolean context. The falsy values are:

False, None, 0, 0.0, "", [], (), {}, set(), and range(0).

Everything else is truthy — including "False", "0", [0], and {"a": None}.

So if chunks: is a clean way to say "if the list is not empty". But if score: is a bug when 0.0 is a legitimate score; write if score is not None:.

bool is a subclass of int: True == 1 and False == 0. That is why sum([True, False, True]) returns 2, which is a neat way to count matches.

is vs ==

== compares values. is compares identity — whether both names point to the same object.

Use is only for singletons: is None, is True, is False, and sentinel objects.

Use == for everything else. x is 1000 may be False even when x == 1000, because small integers are cached and larger ones are not. Comparing strings or numbers with is produces bugs that appear only with certain inputs.

The correct null check is if value is None:.

Logic operators and any/all

and, or, not short-circuit: and stops at the first falsy value, or stops at the first truthy one. That is what makes if data and data[0] > 5: safe on an empty list — the second condition never runs.

They return an operand, not a bool: "" or "default" returns "default". Handy for fallbacks, though if x is None is clearer when 0 or "" are valid values.

any(iterable) is True if at least one element is truthy; all(iterable) is True if every element is (and True for an empty iterable). Both are ideal for validation over a batch.

Chained comparisons read like mathematics: 0.0 <= score <= 1.0 evaluates score once and is clearer than joining with and.

Copy-paste examples

Copy into your own editor, or load one into the compiler below and press Run.

What is truthy

The falsy list is short — memorise it.

values = [False, None, 0, 0.0, "", [], {}, set(), "False", "0", [0], 0.1, " "]
for v in values:
    print(f"{repr(v):10} -> {bool(v)}")

print("\nbool is an int:", True == 1, False == 0)
print("count of correct answers:", sum([True, False, True, True]))

The 0.0 score bug

The first check silently drops a valid zero score.

def report_buggy(score):
    if score:
        return f"score={score}"
    return "no score provided"

def report_correct(score):
    if score is not None:
        return f"score={score}"
    return "no score provided"

for score in [0.85, 0.0, None]:
    print(f"{str(score):5} buggy: {report_buggy(score):22} correct: {report_correct(score)}")

is vs ==

Use is only with None, True, False, and sentinels.

a = [1, 2, 3]
b = [1, 2, 3]
c = a

print("a == b:", a == b, "(same value)")
print("a is b:", a is b, "(different objects)")
print("a is c:", a is c, "(same object)")

x = None
print("correct null check:", x is None)

big1 = 1000
big2 = 1000
print("large int identity is unreliable:", big1 is big2, "| value equality:", big1 == big2)

Short-circuit, any, and all

any and all express batch validation in one line.

chunks = []
print("safe on empty list:", bool(chunks and chunks[0]))

model_name = "" or "default-model"
print("fallback:", model_name)

scores = [0.91, 0.72, 0.85]
print("all above 0.7 :", all(s > 0.7 for s in scores))
print("any below 0.8 :", any(s < 0.8 for s in scores))
print("all on empty  :", all([]), "<- vacuously true")

score = 0.95
print("chained range check:", 0.0 <= score <= 1.0)

Validate a batch of predictions

Try it — in-browser Python

Set one score to None or 1.4 and see which validation rule catches it.

Output

Python runs in your browser. First run downloads the runtime.

Press Run (or Ctrl+Enter) to execute.

CPython in WebAssembly. Stdlib works. NumPy, pandas, scikit-learn and Matplotlib load on demand, and charts render below. No input(), no GPU, no network installs.

Takeaways

  • Falsy: False, None, 0, 0.0, "", [], (), {}, set(). Everything else is truthy.
  • Use `is` only for None/True/False; use == for values.
  • any() and all() express batch validation cleanly; all([]) is True.