Definition
A program spends its time deciding. Is this user an adult, is this basket empty, does this file exist? Those questions allow only two answers, and a type was needed to hold them, just as one exists for numbers and one for text. That type is called bool, after the mathematician George Boole.
It holds only two possible values, True and False, both written with a leading capital: true in lowercase does not exist in Python and raises a name error. It is the type every comparison hands back, and the one Python evaluates behind an if, behind a while or behind a filter.
age = 20
adult = age >= 18 # the comparison produces a value, it can be stored
print(adult) # True
print(type(adult)) # <class 'bool'>That example shows a comparison does not belong to the if: it builds an ordinary value, one you can keep in a variable or pass to a function.
The name bool also refers to a conversion function: bool(value) answers true or false for any object at all. Python calls it behind the scenes every time a condition is evaluated, and that changes the way code gets written, since an empty list is then enough to make a test.
What Python treats as false
Since any object at all can end up inside a condition, a rule was needed for values that are neither true nor false by nature, such as a list or a string. It fits in one idea: whatever is empty or zero counts as false, everything else counts as true. The table below gives the full list, then the cases people wrongly take for false.
| Value | What bool() returns |
|---|---|
0 and 0.0 | False |
"", the empty string | False |
[], {}, () | False |
None | False |
-1, 0.1, "0" | True |
| Any other object | True by default |
The second to last row is the one that catches people out. A negative number is true because the rule says nothing about signs, only about zero: a negative balance passes an if balance: just as well as a positive one.
The string "0" is true because what counts, for a string, is its length and never what it says. That is where a very common bug on values typed at the keyboard comes from, since the input function always hands back text: if answer: stays true even when the person typed zero.
The and and or operators do not return a boolean, but one of their two operands: "" or "anonymous" is the string "anonymous", not True. That is what makes name = entry or "anonymous" possible.
Converting without getting it wrong
The need shows up in every program: a value arrives from outside, from a form or a configuration file, and a yes or a no has to be drawn from it. The reflex is to call bool() on it, since that is the conversion function. That is exactly what must not be done.
Everything fits in one line: bool("False") is True. The five-letter string has nothing to do with the boolean of the same name: to bool(), it is a non-empty string like any other, so it is true.
answer = "False"
print(bool(answer)) # True: the string is not empty
print(answer == "False") # True: comparison written by hand
print(answer.lower() == "true") # False: the usual formThe third line shows the recommended way: the case is lowered, then the text is compared to the expected value, so that "True", "true" and "TRUE" are all treated the same. Nothing stops a program from also accepting "1" or "yes": that decision belongs to the program, not to the language.
A configuration file read back with bool() switches on everything it is meant to switch off: the line debug = False becomes True, and debug mode stays on in production without a single error message.
A boolean is also an integer
Here is a property that looks like an internal detail and turns out to help every day: the bool type inherits from int. A boolean is an integer, with True counting as 1 and False as 0 in the smallest calculation.
The consequence is immediate: counting the true cases in a series comes down to adding them up, with no counter to increment and no loop to write.
marks = [12, 8, 15, 4, 18]
passes = sum(mark >= 10 for mark in marks) # five booleans added up
print(passes) # 3The second line produces one boolean per mark, which sum adds up as 1s and 0s. That kinship also explains two oddities: True + True gives 2, and isinstance(True, int) answers true. The day a function has to reject True where it expects a quantity, the check therefore goes through type(value) is bool.
Frequently asked questions
Should if active == True be written?
No. When the variable already holds a boolean, if active: says the same thing in fewer characters, and the negative form is written with not. The explicit comparison even turns wrong as soon as the value is not a boolean: a non-empty list is true inside an if, while comparing it to True returns False.
Why does an empty list behave like False?
Because collections answer about their contents: a length of zero counts as false, a positive length as true. That is the information len gives, and it allows if results: to be written rather than if len(results) > 0:, which has to be translated in your head.
How can all the items of a list be checked for truth?
With all, which returns True as long as no item is false, and with any, which answers as soon as a single one is. Both accept a generator expression, which avoids building an intermediate list purely to test it. These reflexes are practised on real cases in the Python course.