Modulus operator

  • The modulus operator is used with integers
  • It returns the remainder of a division operation
  • You will find that you use it more than you think you will

In [1]:
7 // 3 # Floor division results in the quotient


Out[1]:
2

In [2]:
7 % 3 # Modulus returns the remainder


Out[2]:
1

Boolean expressions

  • A boolean (or bool in Python) is a True or False value
  • A boolean expression is an expression that results in either a True or False
  • We have already seen a simple operator that produces a boolean: ==

In [3]:
5 == 5


Out[3]:
True

In [4]:
5 == 4


Out[4]:
False
  • True and False are not strings, nor are the equivalent to strings
  • They belong to the bool datatype
  • There are other relational operators besides ==:
    • != Not equal
    • > Greater than
    • < Less than
    • >= Greater than or equal to
    • <= Less than or equal to
  • Remember that = is an assignment operator and == is a relational operator that tests equality

Logical operators

  • There are 3 logical operators:
    • and
    • or
    • not
  • They mean the same thing in Python that they do in English

In [5]:
True and True


Out[5]:
True

In [6]:
True and False


Out[6]:
False

In [7]:
True or True


Out[7]:
True

In [8]:
True or False


Out[8]:
True

In [9]:
False or False


Out[9]:
False
  • When combining multiple expresssions, don't be afraid to use parenthesis
  • They help make the code more readable and ensure it works as intended

In [10]:
True and (True or False)


Out[10]:
True
  • All operands in a boolean expression should be boolean expressions or boolean variables/values
  • However, Python can bend the rules
  • For example, nonzero numbers are considered True
  • But try to avoid this behavior

Conditional execution

  • When writing programs, we often need the ability to change the behavior of a program depending on the situation
  • Conditional statements give us this ability
  • The simplest version is the if statement

In [11]:
x = 1
if( x > 0 ):
    print( 'x is positive' )


x is positive
  • The boolean expression after the if is called the condition
  • If it is True, then the indented portion is executed
  • It has a similar form as a function definition or a loop
  • These are often called compound statements

Alternative execution

  • Another form of the if statement is alternative execution
  • If there are two possibilities, you can add an else statement

In [12]:
if( 0 == x % 2 ):
    print( 'x is even' )
else:
    print( 'x is odd' )


x is odd
  • The possible paths the code can follow are referred to as branches

Chained conditionals

  • If you have more than two possibilities, you can build a chained conditional
  • This is done by adding one or more elif statements

In [13]:
y = 0
if( x < y ):
    print( 'x is less than y' )
elif( x > y ):
    print( 'x is greater than y' )
else:
    print( 'x and y are equal' )


x is greater than y
  • elif is an abbreviation for "else if"
  • Using chained conditionals, only one branch will be taken
  • Each condition is checked in order from first to last
  • When a condition is met, the branch is executed and the remainder are ignored, even if others would be true as well
  • There isn't a limit on the number of elif statements, butdon't go overboard
  • An else statement isn't required so don't use one if it doesn't make sense

In [14]:
# TODO - calculate a tax rate, tip or GPA example

Nested conditionals

  • One conditional can be nested within another

In [15]:
if( x == y ):
    print( 'x and y are equal' )
else:
    if( x < y ):
        print( 'x is less than y' )
    else:
        print( 'x is greater than y' )


x is greater than y
  • The outer conditional contains two (2) branches
  • The second branch contains another conditional with two (2) branches of its own
  • Note the indentation of the statements
  • Nested conditionals can be difficult to read quickly
  • Avoid them when possible
  • Note that you can use logical operators to simplify conditionals

In [16]:
# Using nested conditionals
if( 0 < x ):
    if( x < 10 ):
        print( 'x is a positive single-digit number' )


x is a positive single-digit number

In [17]:
# Using logical operators - this is easier to read
if( (0 < x) and (x > 10) ):
    print( 'x is a positive single-digit number' )

Recursion

  • We have seen how one function can call another
  • It is also legal for a function to call itself
  • Such functions are called recursive and use a process called recursion

In [18]:
def countdown( n ):
    if( n <= 0 ):
        print( 'Blastoff!' )
    else:
        print( n )
        # Recursive call
        countdown( n - 1 )

countdown( 5 )


5
4
3
2
1
Blastoff!
  • This problem-solving approach is called divide and conquer
  • It breaks a problem in to smaller chunks that are easier to solve
  • In this case, the smaller problem is identical in nature to the previous one, just smaller
  • The function calls itself until n <= 0
  • This is called the base case
  • Recursive functions need at least one base case to function properly, but you can have more
  • You can always convert a recursive function into an iterative function that uses a loop
  • You can also do the reverse and go from an iterative function to a recursive function
  • For some problems it is easier to write a recursive function than an iterative one

Infinite recursion

  • If you forget a base case or have an error in your program so that you never reach a base case, the program will never stop running
  • The recursive function keeps calling itself, but the problem is never smaller
  • This is called infinite recursion and is generally considered bad
  • Due to the way programs work inside a computer, they don't really run forever
  • You usually get a runtime error like a stack overflow or max recursion depth exceeded
  • The exact error depends on the programming language
  • Take care to write your base case conditions carefully to avoid these situations
  • Consider the countdown function from above

In [19]:
def countdown_unsafe( n ):
    if( n == 0 ):
        print( 'Blastoff!' )
    else:
        print( n )
        # Recursive call
        countdown( n - 1 )
  • It has been modified so that the conditional is an equality test
  • What would happen if a non-integer number was passed to the function?

In [20]:
# Uncomment this to see what will happen
# countdown_unsafe( 3.5 )
  • Using <= acts as a failsafe if an incorrect value is passed to the function
  • Always assume the worst can happen and write your code accordingly
  • Think of it as defensive programming (just like defensive driving)

Keyboard input

  • Up to this point we have primarily relied upon hard-coded input for functions
  • Python provides the input function that gets input from the keyboard
  • It returns the user's input as a string value
  • You can pass a prompt as an argument to the function
  • If you want the user's input to start below the prompt add a \n newline character
  • If you need the user's input as something other than a string, convert it
  • Work some examples
  • You can even use the eval function to evaluate it as if it where a Python expression

Debugging

  • Note that when Python indicates that an error was discovered on a particular line, that is only where the problem was detected
  • It does not mean that is the line where the problem actually occurs
  • You may have to look at previous lines of code to find the actual error

Exercises

  • You are given the number of hours in a semester broken down by grade. For example, of Bob's total 16 hours, he got an A in 6 hours (2 classes), a B in 7 hours (2 classes and a lab), and a C in 3 hours (1 class). Write a function calculate_gpa that takes the number of hours for each letter grade A through F and computes the GPA. Test your function with at least three different sets of letter grade hours.

In [21]:
def calculate_gpa( a_hours, b_hours, c_hours, d_hours, f_hours ):
    # INSERT YOUR CODE HERE
    return 0
  • Write a function called calculate_fibonacci that takes a parameter n, denoting the $n$-th fibonacci number, and returns the fibonacci number.

In [22]:
def calculate_fibonacci( n ):
    # INSERT YOUR CODE HERE
    return 0