Truthy and Falsy Values
Concepts covered: Boolean Operators
Every Python object has a truth value. You can read it with bool(x), and and consults it, as do or and not. Among the built-in types, the false values form a short, fixed list: False, None, every numeric zero (0, 0.0, Decimal("0.00")), and every empty container ("", [], (), {}). Every other built-in value is truthy, including several a human would read as false. A class you define can set its own truth value, which the last part of this section covers.
| Value | bool(value) | Why |
|---|---|---|
| `0` | False | numeric zero |
| `-1` | True | any nonzero number |
| `0.0` | False | numeric zero |
| `float("nan")` | True | NaN is not zero |
| `""` | False | empty string |
| `" "` | True | a space is a character |
| `"0"` | True | a 1-character string |
| `"False"` | True | a 5-character string |
| `None` | False | always false |
| `[]` | False | empty list |
| `[0]` | True | a list holding 1 item |
from decimal import Decimal
print(bool(0), bool(0.0), bool(Decimal("0.00")), bool(None))
print(bool(""), bool(" "), bool("0"), bool("False"))
print(bool(-1), bool(float("nan")), bool([]), bool([0]))
is_active = "False"
print(bool(is_active), is_active == "True")Output:
False False False False False True True True True True False True True False
The last line is a classic ingestion bug. A CSV export or a web form delivers is_active as the text "False", and bool() reports True for any non-empty string. bool() checks emptiness and ignores meaning, so a text flag needs an explicit comparison against the spelling the source uses.
What not, and, or return
not x always returns a real bool: not "" is True and not 5 is False. and and or still return an operand, now judged by truthiness: "" or "unknown" is "unknown", 0 and 1/0 is 0 without dividing, and "eu" and 42 is 42. Because bool is a subclass of int, True + True is 2, which is why adding up comparison results counts how many were true.
What does this print?
print(bool("0"), bool(0.0), bool([0]), not None)- False False False True
- True False True True
- True False False True
- True True True False
Falsy and missing are different facts
The retry setting in the short-circuit section already showed or treating 0 and None as the same value. What remains is choosing the right test for each field, and the field's meaning decides it. For units_sold, a store that sold 0 units reported a real number, while a store whose feed never arrived reported None. units_sold is None finds broken feeds; units_sold == 0 finds stores that opened and sold nothing. A daily report usually needs both counts, kept apart, because one is an engineering incident and the other is a sales fact. Keep truthiness for fields where every false value means the same thing. In an optional comment field, "" and None both mean nobody wrote one.
- Truthiness: not units_sold
- None: flagged
- 0: flagged
- 12: passes
- Fits when every false value means nothing arrived
- Identity: units_sold is None
- None: flagged
- 0: passes
- 12: passes
- Fits when 0 is a real measurement
Truth values for your own classes
An instance of a class you define is truthy by default, whatever its attributes hold. Defining __bool__ lets the class decide: Python calls it whenever the object meets bool() or not, and the same goes for and and or. The method must return a real bool; returning 1 raises TypeError: __bool__ should return bool, returned int.
class Batch:
def __init__(self, row_count):
self.row_count = row_count
def __bool__(self):
return self.row_count > 0
class Plain:
pass
print(bool(Batch(0)), bool(Batch(250)), bool(Plain()))
print(Batch(0) or "nothing to load")Output:
False True True nothing to load
Batch(0) is false because its __bool__ returned False, so or passes over it and returns the fallback string. Plain() defines no __bool__ and is truthy even though it holds nothing. A loader can then treat an empty batch like any other false value, with the class itself deciding what empty means.
About this lesson
This section is part of the Python Expressions: Advanced lesson on DataDriven, the home of data engineering. Lessons cover SQL, Python, Spark, data modeling and pipeline architecture, and each section pairs its explanation with worked examples and practice you run as you go.