Python truth testing asks an object for a boolean interpretation; it does not distinguish every domain state that evaluates as false.
Python truth values: distinguish missing data from valid zero
Operation contract
The discount record permits an explicit zero and uses None for an unspecified amount. Choosing a default with or replaces both states, so it loses the valid zero. An explicit None check preserves the difference. And and or also return selected operands rather than always returning bool values, which matters when their result is later serialized.
Failure and ownership boundary
Empty collections, zero and None can all be false without being interchangeable. Custom __bool__ or __len__ implementations may perform work or raise. NumPy arrays also require an explicit all/any policy instead of treating an arbitrary array as one boolean. NumPy floating-point checks: finite values and declared tolerances and Python JSON validation: reject duplicate members and non-integer amounts expose those boundaries.
Working program
def effective_discount(discount):
if discount is None:
return 25
if type(discount) is not int or discount < 0:
raise ValueError("discount rejected")
return discount
print("or default:", 0 or 25)
print("explicit zero:", effective_discount(0))
print("missing default:", effective_discount(None))
print("selected operand:", "DEL" and "accepted")
try:
effective_discount(False)
except ValueError:
print("boolean amount rejected")Output
or default: 25
explicit zero: 0
missing default: 25
selected operand: accepted
boolean amount rejectedCosts and limits
Testing these built-in scalars has bounded work. A custom truth method can have arbitrary application cost. Short-circuiting skips the second expression only when the first already determines the selected operand.
Common Mistakes
- Do not use or defaults when zero or an empty value is meaningful.
- And and or return operands, not necessarily boolean values.
Connected lessons
Python conditions and loops: distinguish no value from an empty value, Python JSON validation: reject duplicate members and non-integer amounts, NumPy floating-point checks: finite values and declared tolerances.
