17. Boolean logic in depth
Chapter 16 used and, or, and
not to join conditions. They do more than that: knowing
what they really return unlocks tricks that Python code leans
on constantly. This chapter goes deeper into truth.
Truthy and falsy, again
Recall from Chapter 16: in a condition,
False, None,
0, 0.0,
"", and empty collections
count as false. Everything else is true. Python calls those
falsy and the rest truthy.
if 0:
print("zero is truthy") # does NOT print — 0 is falsy in Python
if "":
print("empty is truthy") # does NOT print — "" is falsy in Python
if None:
print("never") # does not print
if 1:
print("one is truthy") # prints
if "hi":
print("non-empty is truthy")# printsIn Python, 0 and "" are falsy. Keep this in
mind whenever you test a value directly.
and and
or hand back a value
Here is what beginners rarely get told: and and
or do not always return True or
False. They return one of their two sides,
unchanged.
a and b— ifais falsy, it returnsa; otherwise it returnsb.a or b— ifais truthy, it returnsa; otherwise it returnsb.
print(5 and 10) # 10 (5 is truthy, so the second value)
print(None and 10) # None (first is falsy, returned as-is)
print(False or "hi") # hi (first falsy, so the second)
print("yes" or "no") # yes (first truthy, returned at once)Used in an if, this behaves like plain true/false logic
— but the returned value is what makes the tricks below
possible.
The default-value trick:
x or default
Because or returns its first truthy side, you can supply
a fallback for a value that might be None. Picture a name
that may be missing:
typed_name = None # nothing was entered
name = typed_name or "stranger"
print("Hello, " + name) # Hello, strangerIf typed_name had held a real value, name
would keep it instead. This x or default line is a common
Python way to fall back to a default — you will see it when a value
might be missing.
Python 3.8 added the walrus operator := and there is
also the pattern value if value is not None else default,
but x or default is shorter and worth knowing for simple
cases where any falsy value should trigger the fallback.
Open exercises/17/01-default.py. chosen is
set to None. Use chosen or "rock" to fall back
to "rock", then print it. Set chosen to a real
word and run again.
Short-circuit: the second side is skipped
and and or are lazy. They
stop as soon as the answer is certain:
a and b— ifais falsy,bis never even looked at.a or b— ifais truthy,bis never looked at.
This lets the first test guard the second, which runs only after the first has passed:
total = 90
count = 0
# the average is only worth working out when count is not zero,
# so the count check guards the division
if count > 0 and total / count > 20:
print("high average")
else:
print("no average to show")Because count > 0 is False, Python never evaluates
total / count — it short-circuits straight to the
else. The pattern
if x > 0 and something-using-x shows up constantly.
not flips truthiness
not turns any value into a real boolean —
True if it was falsy, False if it was
truthy:
print(not None) # True
print(not 0) # True (0 is falsy, so "not 0" is True)
print(not False) # True
print(not 1) # False (1 is truthy)It is handy for asking "is this missing?":
key = None
if not key:
print("You need a key.")Homework
Homework files are in exercises/17/homework/.
Problem 1 — Default colour
Open exercises/17/homework/01-default-colour.py.
fav holds a colour or None. Using
or, set colour to fav, or to
"blue" when fav is None, then
print Your colour is <colour>. Run it once with
fav = None and once with a real colour.
Problem 2 — Truthy table
Open exercises/17/homework/02-truthy.py. For each of
these values, print the value and whether it is truthy, using
bool(value) to convert it to a real boolean:
0, "", None, False,
"hi", 1. The bool() function
gives True for truthy values and False for
falsy ones.
Problem 3 — Guarded division
Open exercises/17/homework/03-guarded.py. Two numbers:
total and count (which might be
0). Using and, print the average
total / count only when count is greater than
0; otherwise print no data. Test it with
count set to 0 and to a real number.
Challenge — First value that exists
Open exercises/17/homework/04-first-value.py. Three
variables a, b, c each hold a
string or None. In one line using
or, print the first one with a value, or none
if all three are None. Try different combinations of values
and None.
Stuck or finished? Open the homework solutions page.