Table content of this notebook.
if
statementpass
statement and dropping else
daysInMonth
Acknowledgement. This notebook has been adapted from the Wellesley CS111 Spring 2019 course materials (http://cs111.wellesley.edu/spring19).
Python has two values of the bool
type, written True
and False
. These are called logical values
or Boolean values, named after 19th century mathematician George Boole.
True
type(True)
False
type(False)
true
false
We have seen arithmetic operators that produce as output numerical values. Today, we'll see relational operators that
produce as output Boolean values. Relational operators are used to compare two values.
3 < 5
3 > 2
5 == 5
5 >= 5
6 <= 5
Note: ==
is pronounced "equals" and !=
is pronounced "not equals". This is why we distinguish the pronunciation
of the single equal sign = as "gets", which is assignment and nothing to do with mathematical equality!
Relational operators can also be used to compare strings (in dictionary order).
'bat' < 'cat'
'bat' < 'ant'
'bat' == 'bat'
'bat' < 'bath'
'Cat' < 'bat'
EXPLANATION: How does this comparison of string values work? Python starts by comparing the first character of each string to one another. For example "b" with "c". Because the computer doesn't know anything about letters, it converts everything into numbers. Each character has a numerical code that is summarized in this table of ASCII codes. In Python, we can look up the ASCII code via the Python built-in function ord
:
print(ord('a'), ord('b'), ord('c'))
As you can see, the value for 'b', 98, is smaller than the value for 'c', 99, thus, 'b' < 'c'
. Once two unequal characters are found, Python stops comparing the other characters, because there is no point in continuing. However, if characters are the same, like in 'bat' and 'bath', the comparisons continue until the point in which something that differs is found. In this case, there is an extra 't', making 'bath' greater in value than 'bat'.
Uppercase vs. Lowercase: Counterintuitively, it turns out, the uppercase letters are internally represented with smaller numbers than lowercase letters. See the ASCII table and the examples below:
print(ord('A'), ord('a'))
print(ord('B'), ord('b'))
This explains why the world 'Cat' is smaller than the word 'cat'.
There are three logical operators: not
, and
, or
, which are applied on expressions that are already evaluated as boolean values.
not
¶not expression evaluates to the opposite of the truth value of expression
not (3 > 5)
not (3 == 3)
and
¶exp1 and exp2 evaluates to True
iff both exp1 and exp2 evaluate to True
.
True and True
True and False
(3 < 5) and ('bat' < 'ant')
(3 < 5) and ('bat' < 'cat')
or
¶exp1 or exp2 evaluates to True
iff at least one of exp1 and exp2 evaluate to True
.
True or True
True or False
(3 > 5) or ('bat' < 'cat')
(3 > 5) or ('bat' < 'ant')
in
for Sequences¶Let us practice some predicates and conditionals that involve sequences. A sequence is an ordered collection of items. For example, in Python a string
is a sequence as it is an ordered collection of letters. A list
in python is a another sequence and stores an ordered collection of items, enclosed within []
.
We will study strings and lists in more detail in the coming lectures. Today we will use the in
operator and not in
operators to create Boolean expressions involving sequences.
in
operator: s1 in s2
tests if string s1
is a substring of string s2
not in
operator: returns the opposite of in
, i.e., s1 not in s2
is the same as not s1 in s2
'134' in 'CS134'
'era' not in 'generation'
'grass' not in 'grassroots'
Lists and the in
operator: A list in python is just a collection of values enclosed in []
.
item in myList
tests if item
is present in the list myList
.
evenNums = [2, 4, 6, 8, 10] # list of even numbers less than equal to 10
4 in evenNums
5 in evenNums
nameList = ['Anna', 'Chris', 'Zoya', 'Sherod', 'Zack']
'Shikha' in nameList
'Chris' in nameList
Definition: A predicate is simply any function that returns a boolean value. Usually, the function body will contain a complex expression combining relational and logical expressions, as the following examples show.
def isHogwartsHouse(s):
'''Given a string, returns True if it is a Hogwarts house'''
return (s == 'Gryffindor' or s == 'Hufflepuff'
or s == 'Ravenclaw' or s == 'Slytherin')
# notice the use of parenthesis to enclose multi-line expressions
isHogwartsHouse('Slytherin')
isHogwartsHouse("Hagrid's hut")
Expressing intervals of numbers: Below is a predicate that checks if a value is within a given interval of numbers.
def isBetween(n, lo, hi):
"""determines if n is between lo and hi"""
return (lo <= n) and (n <= hi)
More fun with Math: Is a number divisible by a factor?
def isDivisibleBy(num, factor):
return (num % factor) == 0 # notice the remainder operator
isDivisibleBy(121, 11)
isDivisibleBy(25, 3)
Let us practice some predicates and conditionals that involve strings. We will write a predicate isVowel
that takes a character as input and returns true if it is a vowel. There are two ways to write such a predicate.
Helper function lower(): word.lower()
returns a new string which is the string word
in all lowercase letters.
# define the isVowel function
def isVowel1(char):
'''Takes a char as input and determines if it is a vowel.
Function version without in'''
c = char.lower()
return c == 'a' or c == 'e' or c == 'i' or \
c == 'e' or c == 'o' or c == 'u'
# can also use \ for multi-line expressions
def isVowel2(char):
'''Takes a char as input and determines if it is a vowel.
Function version using in'''
c = char.lower()
return c in 'aeiou'
help(isVowel1) # calling help on a function returns its docstring
print(isVowel1('e'), isVowel2('e'))
print(isVowel1('b'), isVowel2('b'))
print(isVowel1('U'), isVowel2('U'))
An if
statement (also called a condtional statement) chooses between two branches based on a test value.
def abs(n):
'''Return the absolute value of the number n'''
if n >= 0:
return n
else:
return -n
def classify(num):
'''Return a string indicating whether num is negative or not.'''
if num < 0:
return 'negative'
else:
return 'nonnegative'
abs(-17)
abs(111)
classify(-17)
classify(111)
A function with a conditional might print something.
def doWhenTemperature(temp):
if temp <= 65:
print("Put on a sweater or coat.")
else:
print("You can wear short sleeves today.")
doWhenTemperature(72)
doWhenTemperature(50)
Does doWhenTemperature
return anything?
print(doWhenTemperature(50))
def categorize(num):
'''This function has 3 statements in its body.
They are executed from top to bottom, one after the other.
'''
print('Categorizing', num)
if num % 2 == 0:
print("It's even")
else:
print("It's odd")
if num < 0:
'''This branch has 2 statements.'''
print("It's negative")
print("(That means it's less than zero)")
else:
print("It's nonnegative")
categorize(111)
categorize(-20)
pass
statement and dropping else
¶When we don't want to do anything in a conditional branch, we use the special pass
statement, which means "do nothing". (It's a syntax error to leave a branch blank.)
def warnWhenTooFast(speed):
if speed > 55:
print("Slow down! You're going too fast")
else:
pass # do nothing
warnWhenTooFast(75)
warnWhenTooFast(40)
It's OK to have an if
statement without an else
clause. In this case, the missing else
clause is treated as if it were a pass
statement.
def warnWhenTooFast2(speed):
if speed > 55:
print("Slow down! You're going too fast")
warnWhenTooFast2(75)
warnWhenTooFast2(40)
Below are two correct variants of the abs
absolute value function defined above. Explain why they work.
def abs2(n):
'''returns the absolute value of n'''
result = n
if n < 0:
result = -n
return result
print(abs2(-17), abs2(42))
def abs3(n):
'''returns the absolute value of n'''
if n < 0:
return -n
return n
print(abs3(-17), abs3(42))
It often make sense to have a conditional statement nested inside the branch of another conditional.
Below we show variants of a function that returns the movie rating appropriate for a given age of movier goer. (If you want to learn more about film ratings, read this Wikipedia article.)
def movieAge1(age):
if age < 8:
return 'G'
else:
if age < 13:
return 'PG'
else:
if age < 18:
return 'PG-13'
else:
return 'R'
movieAge1(5)
movieAge1(10)
movieAge1(15)
movieAge1(20)
Python uses chained (multibranch) conditionals with if
, elif
s, and else
to execute exactly one of several branches.
def movieAge2(age):
if age < 8:
print('G')
elif age < 13:
print('PG')
elif age < 18:
print('PG-13')
else:
print('R')
movieAge2(5)
movieAge2(10)
movieAge2(15)
movieAge2(20)
Remember: Only the first true branch will be executed.
Important: As shown in the following example, the order of chaining conditionals matters!
def movieAgeWrong(age):
if age < 18:
print('PG-13')
elif age < 13:
print('PG')
elif age < 8:
print('G')
else:
print('R')
movieAgeWrong(5)
movieAgeWrong(10)
movieAgeWrong(15)
movieAgeWrong(20)
daysInMonth
¶Define a function named daysInMonth
that takes a month (as an integer) as the argument, and returns the number of days in it, assuming the year is not a leap year. Assume 1 is January, 2 is February, ..., 12 is December. If the month does not fall between 1 and 12, return an error message as a string. Make the function as concise as possible (group months by days, don't write 12 separate if-else clauses).
# Define your daysInMonth function below
def daysInMonth(month):
'''Given a month between 1-12, returns the number of days in it,
assuming the year is not a leap year'''
if month < 1 or month > 12:
return 'Error: Month does not fall between 1-12'
elif month == 2:
return 28
elif month == 4 or month == 6 == month == 9 or month == 11:
return 30
else:
return 31
daysInMonth(4) # April
daysInMonth(8) # August
daysInMonth(2) # February
daysInMonth(13) # Error message
Having seen conditional statements, you may be tempted to use them in predicates. But most predicates can be defined without conditionals by using combinations of relational and logical operators. For example, compare the complicated and simplifed functions below:
def isFreezingComplex(temp):
if temp <= 32:
return True
else:
return False
def isFreezingSimple(temp):
return temp <= 32
print(isFreezingComplex(20), isFreezingSimplified(20))
print(isFreezingComplex(72), isFreezingSimple(72))
def isPositiveEvenComplex(num):
if num > 0:
if num % 2 == 0:
return True
return False
return False
def isPositiveEvenSimple(num):
return num > 0 and num % 2 == 0
print(isPositiveEvenComplex(12), isPositiveEvenSimple(12))
print(isPositiveEvenComplex(19), isPositiveEvenSimple(19))
print(isPositiveEvenComplex(-3), isPositiveEvenSimple(-3))