True, False, and what Python counts as nothing
Comparisons produce a value you can store
>>> 5 > 3
True
>>> age = 17
>>> can_vote = age >= 18
>>> can_vote
FalseTrue and False are values like any other. You can put them in a variable, in a list, pass them to a function. They are capitalised — true is a NameError.
The comparison operators: == equal, != not equal, <, >, <=, >=. And two that read like English: in for membership, not in for its opposite.
"a" in "cat" # True
3 in [1, 2, 3] # True
"rent" in {"food": 200} # False — dicts check keysPython allows chained comparisons, which most languages do not:
if 0 <= score <= 100:That means what it looks like. In C or Java the same line silently computes something else.
== against is
== asks are these values equal. is asks are these the same object in memory. They are different questions and only one of them is usually the one you want.
a = [1, 2, 3]
b = [1, 2, 3]
a == b # True — same contents
a is b # False — two separate listsWhat makes this dangerous is that is appears to work on small numbers and short strings:
x = 256
y = 256
x is y # True on CPython
x = 257
y = 257
x is y # False on CPythonCPython caches the integers from -5 to 256 as single shared objects, so is accidentally gives the right answer below that boundary and the wrong one above it. Code that uses is for numbers passes every small test and fails in production on a big value.
The rule: use is only with None, True and False. For everything else, ==.
Truthiness — what counts as nothing
Any value can be used where a condition is expected. Python treats these as false:
FalseNone- zero of any numeric type:
0,0.0 - empty containers:
"",[],{},(),set()
Everything else is true, including "0", "False" and [0] — each of those is a non-empty container or string. That first one bites when reading text files: the string "0" from a CSV is true.
So the idiomatic test for an empty list is:
if not items:
print("nothing to do")rather than if len(items) == 0. Both work; the first is what Python code looks like.
and and or do not return booleans
This surprises people who know other languages. and and or return one of the operands, not True/False:
>>> "" or "default"
'default'
>>> "Asha" or "default"
'Asha'
>>> 0 or "default"
'default'That gives the common idiom name = user_input or "guest", which fills in a default when the input is empty.
And it gives the bug: if the legitimate value is 0, "" or an empty list, the default silently replaces it.
quantity = form_value or 1 # a genuine order of 0 becomes 1When zero is a real answer, test for None explicitly:
quantity = 1 if form_value is None else form_valueThey also short-circuit: a and b never evaluates b if a is false. This is not an optimisation detail, it is how you write safe checks:
if items and items[0] == "x": # safe on an empty listReverse the two halves and an empty list raises IndexError.
Booleans are integers
True == 1 and False == 0, genuinely, and this is occasionally useful:
flags = [True, False, True, True]
sum(flags) # 3Counting how many things passed a test is sum(1 for x in items if test(x)) or just sum(test(x) for x in items).
The comparison that quietly lies
>>> "10" < "9"
TrueStrings compare character by character, left to right, so "1" sorts before "9" and the whole string does too. Nothing errors. A list of version numbers or ages read from a file and never converted will sort in an order that looks random and is perfectly consistent. This is the same failure as the one in the input() lesson, showing up in sorting rather than in arithmetic.
Comparing a string to a number, though, does raise:
>>> "10" < 9
TypeError: '<' not supported between instances of 'str' and 'int'Python 3 refuses rather than inventing an ordering. Python 2 did invent one, which is why old code silently produced nonsense.
The one thing to keep
`or` returns an operand rather than a boolean, so `x or default` quietly replaces a legitimate 0 or empty string, and `is` should be reserved for None.
Before you move on
A form handler writes `discount = entered or 10` so that a blank field becomes 10 percent. A shopkeeper enters 0 to mean no discount and is charged 10 percent off anyway. Why?
Pick the one you would defend. Nobody sees your answer.