Values, types and names · about 30 min

Booleans and None

Why this matters

Programs constantly ask yes-or-no questions: is the file there, is the password right, is the list empty? The answers are booleans. Programs also need a way to say "there is no value here": no result yet, no match found, no argument given. Python's answer is None. Both are tiny types, but they appear in almost every line of real code, and they have some precise behaviors (booleans are integers; there is only one None) worth knowing exactly.

bool: True and False

The type bool has exactly two values, written True and False (capitalized; true is a NameError). You get them from comparisons:

age = 20
print(age >= 18)
print(age == 21)
print(age != 21)
print(type(age > 5))
True
False
True
<class 'bool'>

The comparison operators are == (equal), != (not equal), <, <=, >, >=. Remember: = binds a name, == compares. The next module covers combining booleans with and, or and not, and the related idea of "truthiness".

Booleans can be stored in names like any value:

is_adult = age >= 18
print("adult?", is_adult)
adult? True

Naming them like a question (is_adult, has_errors, found) makes code read naturally.

bool is a subclass of int

Historically Python had no boolean type and used 1 and 0. When bool was added (Python 2.3), it was made a subclass of int for compatibility: True is an int with value 1 and False an int with value 0, which just print differently.

print(isinstance(True, int))
print(True == 1, False == 0)
print(True + True)
print(False * 10)
True
True True
2
0

A practical use: counting how many conditions are true by adding them up.

a, b, c = 4, -1, 7
print((a > 0) + (b > 0) + (c > 0))
2

(a, b, c = 4, -1, 7 binds three names at once; module 3 explains this tuple assignment.)

Underneath, True and False are two pre-built objects that CPython creates at startup. Every comparison returns one of those two objects; it never creates a new boolean. So True is True always holds.

Note: Because True == 1, using both as dictionary keys or set members treats them as the same key. A surprise you will rarely hit, but now you will recognize it.

None: the absence of a value

None is a special object meaning "nothing here". Its type is NoneType, and that type has exactly one instance: there is only ever one None object in a running program. An object like this is called a singleton.

You meet None in three typical places.

Functions that return nothing. Every function returns something; if it has no useful result, it returns None:

result = print("hello")
print(result)
print(type(result))
hello
None
<class 'NoneType'>

Placeholders. A name that will get a real value later, or a value meaning "not known":

best_score = None     # no games played yet
middle_name = None    # not everyone has one

"Not found" results. For example, the dictionary method get (module 7) returns None when a key is missing, and regular expression searches return None when nothing matches.

The REPL does not echo None: typing an expression that evaluates to None shows nothing. That is why print("x") in the REPL shows x only once (printed by print), not x followed by None.

Testing for None: use is

Since there is exactly one None, the right test is identity:

middle_name = None
print(middle_name is None)
print(middle_name is not None)
True
False

is not is a single operator meaning "is a different object from". You will usually see this inside an if (next modules):

if middle_name is None:
    print("no middle name")

Why not == None? It usually gives the same answer, but == can be redefined by a class, so an object could claim to equal None. is cannot be fooled, is faster, and every Python style guide (PEP 8) recommends it.

None is not False, not 0, not ""

None, False, 0 and the empty string "" are four different objects:

print(None == False)
print(None == 0)
print(None == "")
False
False
False

They do share one property, "falsiness", which you will meet with if in the next module: all four count as false in a condition. But a function that returns 0 (a real answer: zero items) and one that returns None (no answer) mean different things. Keep them apart.

Common mistakes

Recap

Going further: in the REPL, try int.__subclasses__() and look for bool, and type(None)(): calling NoneType returns the same singleton rather than a new object.

Exercises

Exercise 1 · quiz

Booleans are numbers

What does print(True + True + False) print?

Answer
  • 2

bool is a subclass of int: True behaves as 1 and False as 0 in arithmetic. So the sum is 2 (an int, not a bool). This is occasionally handy, for example to count how many conditions hold.

Exercise 2 · quiz

What does print return?

What does this program print? Type both lines, separated by a space.

result = print("hi")
print(result)
Answer

print writes hi as a side effect, then returns None, because it has no useful result to give back. Any function that does not explicitly return a value returns None. So result is bound to None, and printing it shows None.

Exercise 3 · write code

Count with booleans

Read three whole numbers, one per line. Print how many of them are strictly greater than zero, labeled exactly like this (for inputs 5, -2, 9):

positive: 2

You have not learned if yet, and you do not need it: a comparison such as a > 0 produces True or False, and booleans add up like 1 and 0.

File: main.py

Starting point

a = int(input())
b = int(input())
c = int(input())

Example

input

5
-2
9

expected output

positive: 2

Example

input

0
0
1

expected output

positive: 1
Hint 1

a > 0 is True or False.

Hint 2

True + False + True is 2.

Hint 3

Use parentheses: (a > 0) + (b > 0) + (c > 0); comparisons bind more loosely than +.

Reference solution
a = int(input())
b = int(input())
c = int(input())
print("positive:", (a > 0) + (b > 0) + (c > 0))

Exercise 4 · quiz

Testing for None

Which is the idiomatic way to check whether value is None?

Answer
  • value is None

There is exactly one None object in a running program (it is a singleton), so identity is the precise test. == None usually works but can be fooled by objects that define their own equality, and it is slower. type(value) == None is always False (the type is NoneType), and value = None is an assignment, not a test.

Exercise 5 · write code

A boolean in disguise

Read a whole number n. Compute flag = n > 10. Print four lines exactly as below (for input 12):

flag: True
type: bool
is an int: True
flag * 100: 100

Use type(flag).__name__ for the second line and isinstance(flag, int) for the third.

File: main.py

Starting point

n = int(input())
flag = n > 10
print("flag:", flag)

Example

input

12

expected output

flag: True
type: bool
is an int: True
flag * 100: 100

Example

input

3

expected output

flag: False
type: bool
is an int: True
flag * 100: 0
Hint 1

isinstance(True, int) is True because bool is a subclass of int.

Hint 2

False * 100 is 0.

Reference solution
n = int(input())
flag = n > 10
print("flag:", flag)
print("type:", type(flag).__name__)
print("is an int:", isinstance(flag, int))
print("flag * 100:", flag * 100)