CS134 Conditionals and Modules

In this lecture, we will continue our discussion of conditionals in Python.

Last lecture, we looked at some simple if-else conditional statements. Note that the else block is optional.

Today we will discuss the logical operators and, or, and not in Python to construct more complicated Boolean expressions, in addition to nested conditionals.

Logical operators: and, or, not

The logical operators and, or and not in Python are used to combine Boolean values and write more complex Booleans expressions.

and

boolExp1 and boolExp2 evaluates to True iff both boolExp1 and boolExp2 evaluate to True.

or

boolExp1 or bool Exp2 evaluates to True iff at least one of boolExp1 and boolExp2 evaluate to True.

not

not boolExp evaluates to True iff boolExp evaluates to False.

Let us try these out.

20 < 13 and 6 == 6
False
20 < 13 or 6 == 6
True
not 20 < 13
True
not 6 == 6
False

Example 1. Check if a number is divisible by 5 and is odd.

def oddMultipleFive(num):
    "Returns true if num is divisible by 5 and odd"
    return num % 5 == 0 and num % 2 == 1 
oddMultipleFive(55)
True
oddMultipleFive(80)
False

Example 2. Ask the user to enter a lowercase letter. Check if it is a vowel or consonant.

def isVowel(letter):
    """Takes lowercase letter as input and returns 
    True if it is a vowel, else returns False"""
    # can do an if else or since we are 
    # returning the truth value of expression, 
    # can directly return
    return (letter == 'a' or letter == 'e' or letter == 'i' 
            or letter == 'o' or letter == 'u') 
isVowel('b')
False
isVowel('a')
True
isVowel('z')
False

Some takeways.

  • We can chain together a bunch of boolean expressions (not just two).

  • It does not make sense, however, to write letter == 'a' or 'e' or 'i' or 'o' 'u': logical operators take bool type operands, not strings.

Example 3. Write a function divide that takes two numbers num1 and num2 as input, and returns the result of num1/num2 as long as num2 is not zero. If num2 is zero, print “Cannot divide by zero” and return None.

def divide(num1, num2):
    if not (num2 == 0):  # can also write num2 != 0
        return num1/num2
    else:
        print("Cannot divide by Zero")
    # do we need to say anything after this?
    # if we get here we will implicitly return None
divide(7, 3)
2.3333333333333335
divide(9, 0)
Cannot divide by Zero

Nested Conditionals

Sometimes, we may encounter a more complicated conditional structure. Consider the following example.

Write a function weather that takes as input a temperature temp value in Fahrenheit.

  • If temp is above 80, print “It is a hot one out there.”

  • If temp is between 60 and 80, print “Nice day out, enjoy!”

  • If temp is below 60 and above 40, print “Chilly day, wear a sweater.”

  • If temp is below 40, print “Its freezing out, bring a winter coat!”

Question. How can we organize this using if-else statements?

Attempt 1: Nested If Else

Does the following work?

def weather1(temp):
    if temp > 80:
        print("It is a hot one out there.")
    else:
        if temp >= 60:
            print("Nice day out, enjoy!")
        else:
            if temp >= 40:
                print("Chilly day, wear a sweater.")
            else:
                print("Its freezing out, bring a winter coat!")
weather1(89)
It is a hot one out there.
weather1(72)
Nice day out, enjoy!
weather1(55)
Chilly day, wear a sweater.
weather1(33)
Its freezing out, bring a winter coat!

Attempt 2: Only Ifs

The above function is hard to read with so many indented blocks. What if we used only ifs? What is the trade off?

def weather2(temp):
    if temp > 80:
        print("It is a hot one out there.")
    if temp >= 60 and temp <= 80:
        print("Nice day out, enjoy!")
    if temp <60 and temp >= 40:
        print("Chilly day, wear a sweater")
    if temp < 40:
        print("Its freezing out, bring a winter coat!")
weather2(89)
It is a hot one out there.
weather2(72)
Nice day out, enjoy!
weather2(55)
Chilly day, wear a sweater
weather2(33)
Its freezing out, bring a winter coat!

Class Discussion

  • What is the difference between Attempt 1 and Attempt 2? Can we trace the control flow through each?

  • What are the pros, cons of each attempt?

Chained if, elif, else Conditionals

If we only need to execute one out of several conditional branches, we can use chained (or multi-branch) conditionals with if, elif, and else to execute exactly one of several branches.

If Else Statement Syntax

if (boolean expression a):
       statement 1
      …
elif (boolean epression b):
       statement 2
      …
else:
       statement 3
statement 4

  • If bool expression a is True: only statement 1 and 4 are executed, regardless of the boolean exp b

  • If bool expression a is False and b is True: only statement 2 and 4 are executed

  • If bool expression a and b are both False: only statement 3 and 4 are executed

def weather3(temp):
    if temp > 80:
        print("It is a hot one out there.")
    elif temp >= 60:
        print("Nice day out, enjoy!")
    elif temp >= 40:
        print("Chilly day, wear a sweater.")
    else:
        print("Its freezing out, bring a winter coat!")
weather3(89)
It is a hot one out there.
weather3(72)
Nice day out, enjoy!
weather3(55)
Chilly day, wear a sweater.
weather3(33)
Its freezing out, bring a winter coat!

Takeway

  • Chained conditionals can avoid having to nest conditionals, which improves readability

  • Since only one of the branches in a chained if, elif, else conditional evaluates to True, using them avoids unnecessary checks incurred by chaining if statements one after the other.