Booleans and Conditions

In this lecture, we investigate the notion of variable scope when calling functions.

Then we explore the boolean types True and False in Python, relational and logical operators, and how they help making decisions using the if- else conditional blocks.

Variable Scope

Local variables. An assignment to a variable within a function definition creates/changes a local variable. Local variables exist only within a function’s body, and cannot be referred to outside of it. Parameters are also local variables that are assigned a value when the function is invoked.

def myfunc (val):
    val = val + 1
    print('local val = ', val)
    return val 
val = 3
newVal = myfunc(val)
local val =  4
newVal
4
print('global val =', val)
global val = 3

Boolean Type and Relational Operators

True and False are of type bool in Python and naturally occur as a result of relational operators (<, >, ==, !).

4 < 5 
True
10 == 10
True
'a' == 'b'
False
True == 1
True
False == 0
True
1000/3 < 300
False
num1 = int(input("Enter first number: "))
num2 = int(input("Enter second number: "))
num1 <= num2
num1 != num2
num1 % 3 == 1

Conditional Statement: If Else

We can ensure that some statements in the program are evaluated conditionally only if the result of a Boolean expression evaluates to True using an if statement. If the Boolean expression evalautes to False, then the control flow skips statements under the if block and evaluates the statements under the else block.

If Else Statement Syntax

statement 1
statement 2
if (boolean expression):
       statement 3
       statement 4
      …
else:
       statement 5
       statement 6
      …
statement 7

Indentation matters in Python

Indented statements form a logical block of code in Python:

  • If the boolean expression next to the if statement evaluates to True, then statements 3, 4,... in the if block are executed, after which the control flow will skip over all of the statements under the else block, and go straight to statement 7

  • If the boolean expression next to the if statement evaluates to False, then the control flow skips over statements 3, 4,.. and exectutes statements 5, 6,... in the else block, after which the control flow goes to statement 7.

Checking if Number is Even

Let us write a function printEven that takes a number as input. If the number is even, it prints “Even”, else it prints “Odd”.

Question. How can we check if a number is even?

3 % 2
1
10 % 2
0
17 % 2
1
9 % 2 == 0
False

Exercise. Let us write the function isEven(num) below.

def printEven(num):
    """Takes a number as input, prints Even if
    it is even, else prints Odd"""
    if num % 2 == 0: # if even
        return True
        print("Even")
    else:
        return False
        print("Odd")
printEven(16)
True
printEven(77)
False

Exercise. Suppose instead of printing, we want to return True if number is Even, and False if number is Odd. Let us define an isEven(num) that does this.

def isEven(num):
    """Takes a number as input, returns True if
    it is even, else returns False"""
    if num % 2 == 0: # if even
        return True
    else:
        return False
isEven(8)
True
isEven(75)
False

Else block is optional

An if statement does not need an else, and there are often times when removing the else block makes the program simpler.

Simplify. We can simplify the isEven function by removing the else block, and return False if the if condition fails.

def isEven(num):
    """Takes a number as input, returns True if
    it is even, else returns False"""
    if num % 2 == 0: # if even
        return True
    return False

Simplify further. We can shorten it even further and just return the result of the Boolean expression.

def isEven(num):
    """Takes a number as input, returns True if
    it is even, else returns False"""
    return num % 2 == 0

Tracing Control Flow Through Conditionals

Consider the following example of a function zeroToOne() that takes a number num as input. If the number is equal to zero, it adds one to num and returns it. Otherwise it just returns num.

Let us trace the control flow when the function is called with different values of num. We can use print statements in our code to see the control flow of the program.

In situations like this function, it is a good idea to have a single return statement, rather than a return statement in each conditional block.

Notice: Statements above the if block and after the else block are always executed.

# adding more prints and return
def zeroToOne(num):
    """If input number num is 0, adds one and returns,
    else returns num itself"""
    print("You called this function with num =", num)
    
    if num == 0:
        print("Incrementing to 1")
        num += 1 # update to 1
        
    else:
        print("No need to increment.")

    print("Just before return")
    return num
    
    print("Just after return")  # will this ever get printed?