Booleans in Python (Part 1)
Translating from pseudocode
Translating from pseudocode to Python syntax seems pretty straightforward. We capitalize True
and False
but not or
, and
, and not
. For example, running the code
print(True or False)
print(True and False)
print(not False)
gives the output
True False True
In Python, True
and False
are built-in Boolean constants, just like 1, 2, and 3 are built-in numerical constants.
Running the code
print("True")
print(True)
print(type("True"))
print(type(True))
gives the output
True True <class 'str'> <class 'bool'>
Although True
looks exactly like the string “True” when displayed by Python, the value True
is not a string.
This makes translating from pseudocode to Python very straightforward, as long as we avoid quotation marks:
Pseudocode | Python |
---|---|
True | True |
False | False |
or | or |
and | and |
not | not |
Caution
Do not use quotation marks on Booleans True
and False
.
Comparisons
Translation of comparisons from pseudocode also seems straightforward. If we try to check equality using a single equals sign, we will get the cryptic syntax error that tells us that “keyword can't be an expression”: running the code
print("True" = True)
gives the error
Traceback (most recent call last): File "<string>", line 1 SyntaxError: keyword can't be an expression
Since a single equals sign means assignment, two equals signs are used to check equality. For example, running the code
print("True" == True)
gives the output Flase.
We can also check for inequality. For example, running the code
print("True" != True)
gives the output True.
The other types of comparisons look like the ones in pseudocode, but they behave a little differently. You can use a sequence of comparisons on a sequence of values. The entire expression is true if the comparison between each consecutive pair is true. For example, running the code
print(3 < 4 < 5)
print(3 <= 4 < 2)
print(3 == 3 >= 3)
gives the output
True False True
The second expression is False
because 4 < 2
is false. But that isn't the only way that the comparisons are a little surprising. We can also use them to compare strings. For example, running the code
print("A" != "a")
print("ape" <= "cat")
print("cat" == "cat ")
gives the output
True True False
There isn't anything too surprising here: we know that uppercase and lowercase letters are different, that words can be ordered like in a dictionary, and that a string is not the same as the same string with an extra blank space.
But what if we compare these two strings "cat"
and "Cat"
? Running the code print("cat" < "Cat")
gives the output False. This answer is less obvious. We'll get back to it in a moment.
In this table, the only new information is how to check inequality and two new ways of making comparisons with is
and is not
.
Function | Pseudocode | Python |
---|---|---|
< | < | < |
> | > | > |
≤ | <= | <= |
≥ | >= | >= |
= | == | == |
≠ | Not applicable | != |
Not applicable | Not applicable | is |
Not applicable | Not applicable | is not |
We haven't yet talked about is
and is not
, but will do so later. We have also seen the following:
- Multiple comparisons can be make on one line.
- Strings can be compared.
Caution
Using is
and is not
may give unexpected answers.
You're welcome to investigate is
and is not
, which determine whether or not values have the same memory address, but be prepared not to yet understand what is going on.
Python's approach to Booleans
So, let's see what happens when we put together some Boolean expressions. What if we want to check if a number is between 10 and 20? We can join two smaller expressions using and
or use multiple comparisons on one line:
num = 10
print((10 <= num) and (num <= 20))
print(10 <= num <= 20)
Both give the correct answer:
True True
To check if a person is eligible for a discount based on age, we use or
to join a smaller expression that checks for ages less than 21 and a smaller expression that checks for ages greater than 65:
age = 35
print((age < 21) or (65 < age))
The result is False, as it should be.
Now get ready for some surprises. Running the code
print("False" and "True")
gives the output True.
Based on our understanding of data types, and
should require Booleans. Since False
and True
with quotations marks are strings, we should get an error message. But we don't. Moreover, the answers doesn't seem to make any sense. If the strings are being interpreted as Booleans, why isn't the answer False
? How about running the code
print("cat" or "dog")
Will we get an error message now? Strangely, no. The output is cat. It looks like we can use or
on non-Booleans. Then, can we use Booleans in places where non-Booleans are usually used? It seems so. Running the code
print(True + 4)
gives the output 5. What is going on?
Non-Booleans masquerading as Booleans:
None
, False
, 0, 0.0, ""
Almost everything else
The problem is that Python is very accommodating and flexible. Almost all values are given the Boolean value True
, even if the values themselves are not Booleans. A few values are False
, including None
, False
itself, 0, 0.0, and the empty string. Later we'll see a few other False
values, empty like the empty string.
When we wrote cat
or dog
, the answer was true, since cat and dog are both True
.
Caution
Avoid using Boolean functions on non-Boolean values.
Booleans masquerading as numbers: False
can be 0 and True
can be 1.
You've probably guessed that Python is also being flexible by giving True
and False
numerical values when you try to add them.
Caution
Avoid using mathematical functions on Boolean values.
Strings and character encodings
Now let's look more deeply into the result of comparing the strings cat
and Cat
. The ordering used in comparison is based on code points in Unicode.
Unicode is an international standard for encoding.
It maps each character to a number (code point).
In this encoding standard, each character is assigned a distinct number. When the order of two strings is determined, these numbers are used for comparisons. Here's a partial listing of codepoints:
32 | ! | 33 | " | 34 | # | 35 | $ | 36 |
0 | 48 | 1 | 49 | 2 | 50 | 3 | 51 | 4 | 52 |
0 | 48 | 1 | 49 | 2 | 50 | 3 | 51 | 4 | 52 |
A | 65 | B | 66 | C | 67 | D | 68 | E | 69 |
a | 97 | b | 98 | c | 99 | d | 100 | e | 101 |
But don't worry about the exact numbers. It is the order that is useful to know: the blank space, punctuation, the digits in order, the upper-case letters in order, and the lower-case letters in order. There are many other characters that are encoded as well, but we're not going to worry much about those.
There are built-in functions that determine the code point given a character and that determine the character given a code point:
Function | Python |
---|---|
Code point from character | ord('A') |
Character from code point | chr(65) |
More string functions
There are other functions for Booleans. Here I'll just mention some of the string functions:
Function | Python |
---|---|
Letter | .isalpha() |
Lower case | .islower() |
Upper case | .isupper() |
Number | .isdigit() |
Blank | .isspace() |
These will be handy when we write programs to encrypt strings, as they allow us to check properties of each character. In particular, isalpha()
returns True
if the character is a letter, with islower()
and isupper()
being more specific, checking for lower case or upper case. We can also check for numbers and blanks.
Caution
Use dot notation.
Notice that these all use dot notation, so be sure to put the function names after the input, joined by a period. For example, "My string".isalpha()
.
Caution
Use only on strings.
Remember that these functions only work on strings.