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.

1. Read

Understand the idea in plain English first.

2. Run

Load any example into the compiler and press Run.

3. Change

Edit one value, rerun, and learn from the output.

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.

Hands-on practice

Compiler on the left. Examples on the right.

On desktop, keep the compiler beside the examples. On mobile, the same blocks stack cleanly. Pick an example, try it in the compiler, then change one small thing.

Validate a batch of predictions

Live Python compiler

Try it — in-browser Python

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

Code editor

Output

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

Press Run (or Ctrl+Enter) to execute.

Runs CPython in your browser. NumPy, pandas, scikit-learn and Matplotlib load on demand. Charts appear below the output. No input(), no GPU, no network installs.

Clear code examples

Every example is copy-ready. Use Try in compiler when you want to experiment without scrolling around.

Example

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]))

Example

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)}")

Example

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)

Example

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)

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.