In Python, you can use almost any value as a condition in an if statement — not just the explicit booleans True and False. Every value in Python is considered either "truthy" (treated as true) or "falsy" (treated as false) when it's evaluated in a boolean context, like an if condition or a while loop. Understanding this rule lets you write shorter, more idiomatic conditions — and avoid confusing bugs when a value you expected to be truthy turns out not to be.

What Counts as Falsy?

Python treats a short, fixed list of values as falsy. Everything else is truthy.

falsy_values = [False, None, 0, 0.0, "", [], {}, (), set()]

for value in falsy_values:
    print(f"{value!r:10} -> {bool(value)}")

Output:

False -> False
None -> False
0 -> False
0.0 -> False
'' -> False
[] -> False
{} -> False
() -> False
set() -> False

In plain terms: the number zero (in any numeric type), None, and any empty collection (string, list, dict, tuple, or set) are falsy. A non-empty collection, a non-zero number, and basically everything else — including the string "False", which is just a non-empty string — are truthy.

Using Truthiness Directly in Conditions

This is the practical payoff: instead of explicitly checking a list's length, you can check the list itself.

cart = []

# Explicit, but more verbose
if len(cart) > 0:
    print("Cart has items")
else:
    print("Cart is empty")

# Idiomatic Python — relies on truthiness
if cart:
    print("Cart has items")
else:
    print("Cart is empty")

Output:

Cart is empty
Cart is empty

Both versions behave identically, but experienced Python developers almost always write the second form — if cart: rather than if len(cart) > 0: — because it's shorter and reads naturally as "if there's a cart."

The bool() Function

You can check any value's truthiness directly by passing it to bool(), which is exactly what Python does internally whenever a value appears in a condition:

print(bool("hello"))   # non-empty string
print(bool(""))        # empty string
print(bool(42))        # non-zero number
print(bool(0))         # zero
print(bool([1, 2]))    # non-empty list
print(bool(None))      # None is always falsy

Output:

True
False
True
False
True
False

A Common Gotcha: Zero vs None

Because 0 is falsy, code like if value: will treat a legitimate zero the same as a missing value — which is usually not what you want when zero is a valid, meaningful answer (like a quantity, a score, or an index).

quantity = 0

# BUG: this treats a real quantity of 0 the same as "no quantity given"
if quantity:
    print("Quantity provided")
else:
    print("No quantity provided")  # misleading — 0 is a valid quantity!

# CORRECT: explicitly check for None when you need to distinguish "zero" from "missing"
if quantity is not None:
    print("Quantity provided (even if it's zero)")

Output:

No quantity provided
Quantity provided (even if it's zero)

The rule of thumb: use plain truthiness checks (if value:) when you only care about "is this empty or missing," and use an explicit is not None check when zero (or an empty string) is a meaningfully different answer from "nothing was provided at all." This same truthiness logic also powers the walrus operator and conditions inside a for loop or while loop.