Skip to content

Python · Fundamentals

Python Truthiness and Type Conversion Explained — Falsy Values, and/or, and __bool__

4 min read Updated 2026-06-19 Share:

Practice Truthiness & Type Conversion interview questions

Python truthiness, explained

if my_list: reads naturally, but it relies on Python's truthiness rules — and those rules trip people up around empty containers, and/or return values, and custom objects. This guide covers what's falsy, how and/or actually behave, and how explicit conversion works.

What counts as falsy

Any object can be tested in a boolean context. Python treats these as falsy:

bool(None)     # False
bool(False)    # False
bool(0)        # False — also 0.0, 0j
bool("")       # False — empty string
bool([])       # False — empty list, also (), {}, set()
bool(range(0)) # False — empty range

Everything else is truthy: non-empty containers, non-zero numbers, and any object that doesn't say otherwise.

Prefer truthiness over explicit comparisons

Because empty containers are falsy, the Pythonic way to check for "has items" is the object itself:

items = []
if items:            # idiomatic — checks "non-empty"
    process(items)

if len(items) > 0:   # works, but verbose and un-Pythonic
    process(items)

One important exception: when a value could legitimately be 0 or "" and you need to distinguish it from "missing", check is None explicitly:

def f(timeout=None):
    if timeout is None:    # NOT `if not timeout:` — 0 is a valid timeout!
        timeout = 30

How objects decide their own truthiness

For a custom class, Python checks __bool__ first; if it's absent, it falls back to __len__ (zero length = falsy); if neither exists, the object is always truthy.

class Cart:
    def __init__(self, items):
        self.items = items
    def __len__(self):
        return len(self.items)

bool(Cart([]))       # False — falls back to __len__ == 0
bool(Cart([1, 2]))   # True

class Always:
    def __bool__(self):
        return False

bool(Always())       # False — __bool__ wins

and / or return operands, not booleans

This surprises people: and and or return one of the operands, not True/False. They short-circuit:

"a" and "b"     # 'b'  — and returns the last value if all truthy
"" and "b"      # ''   — and returns the first falsy value
"a" or "b"      # 'a'  — or returns the first truthy value
"" or "b"       # 'b'  — or returns the last if all falsy

This enables the classic default-value idiom (with the same 0/"" caveat as above):

name = user_input or "Anonymous"   # use input, or fall back if empty

For a true boolean negation, not always returns an actual bool: not ""True.

Explicit type conversion

Python doesn't do implicit numeric→string coercion ("x" + 1 is a TypeError), so you convert explicitly with the type constructors:

int("42")          # 42
int("42", 16)      # 66  — parse as base 16
int(3.9)           # 3   — truncates toward zero (not rounding!)
float("3.14")      # 3.14
str(42)            # '42'
list("abc")        # ['a', 'b', 'c']
dict([("a", 1)])   # {'a': 1}
bool([])           # False

int() on a float truncates toward zero, so int(-3.9) is -3. Bad input raises ValueError (int("abc")), which is what you catch when validating user data.

Recap

Falsy values are None, False, numeric zero, and empty containers/strings; everything else is truthy. Write if items: rather than if len(items) > 0:, but use is None explicitly when 0 or "" are valid values you must distinguish from "missing". Custom objects control truthiness via __bool__, falling back to __len__. Remember that and/or return an operand and short-circuit, powering the value or default idiom. Conversions are explicit — int(), float(), str(), list() — and int() on a float truncates toward zero.

More ways to practice

The self-quiz is live. Get notified when mock interviews and new question packs drop.

or
Join our WhatsApp Channel