Week 4: Functions

Announcements

  • Lab 3 available now.

Monday

While loops

For loops allowed us to repeat steps in python, and if statements and Boolean expressions allowed us to ask questions and make decisions based on data values. We now introduce yet another syntactic tool for designing programs in python: the while loop. The while loop is a mix of for loop and an if statement. A typically for loop executes for a definite number of times, but what if we are expecting a user to type in a positive integer, a valid date, or a string with no punctuation? We can trust the user not to make a mistake, but this is not very robust. If we detect that a user made a mistake in typing input, we could ask the user again. But how many times should we ask? Once? Twice? 100 times? The while loop can solve these types of computational problems by repeatedly looping until some type of condition is met. The general syntax is

while <CONDITION>:
  <BODY>

The <CONDITION> is a Boolean expression. When the condition is true, the body of the loop will execute and then re-evaluate the condition. When the condition finally evaluates to false, the python skips the body of the loop and executes the next line after the body.

A for loop can often be written as an equivalent while loop, but some while loops cannot be written as for loops.

Look at some examples in while_loops.py

Wednesday

Functions

Today we’ll introduce another big, key computer science topic: functions. A function is a named sequence of statements that perform a particular operation. Some functions are built in (int,str,float,input,print), but you can also define your own functions. Defining your own functions has many benefits:

  • make programs easier to read/understand

  • minimize programmer error

  • put repeated code into functions

  • hide low-level details of a function until you need to understand them.

In fact, you’ve been defining and using your own functions for a couple of weeks now, with the main() function. This week, we’ll see many more examples of functions. You’ll see that functions can take input and return input, and even do other "side effects" in between.

Function Syntax

Here is the syntax for how to define a function:

def <NAME>(<PARAMETERS>):
  <BODY>

The <NAME> is the name of the function you define. The <BODY> is a series of statements that you want to execute each time you use your function. <PARAMETERS> is a list of zero or more inputs to the function. These parameters can be used inside the function just like any other variable.

Let’s look at some examples in function_examples.py. We have defined four functions so far: printIntro, printStarRow(n), starBox(n), and main(). We will describe a few of these and then have you practice some.

Once a function is defined, you can call the function, by giving the name of the function and specific values for each parameter.

Exercise: practice function definition and calls

Practice defining and calling functions by modifying your program in function_examples.py to implement starBox(n). Call starBox in main with different values of n. Try getting a value from the user with input in main and sending this value to starBox

What happens when a function gets called?

Python does a lot of behind-the-scenes work when a function gets called. Here is an outline of what happens:

Steps that occur when a function is called:

  1. Suspend current function.

  2. Evaluate arguments, copy them to parameters of the called function in order.

  3. Execute called function using set values of parameters.

  4. Return back to the calling function.

When calling a function, arguments are sometimes, but not always plain values. Other times, they are complex expressions. These expressions get evaluated in Step 2 of the process above.

starBox(2**3)

Friday

The return statement.

Often when you define a function, you want the function to return some value back to whatever program called the function. You can do this with the return command. for example, the built-in function input grabs a string of text from the user and returns it as a string. When a return statement is reached, the function stops and immediately returns the value indicated by the return statement.

For example, if you defined a function def add(a,b) to add the values a and b integers, you’ll probably want to define and return a variable result=a+b. Then, once you’ve added the numbers, the return result statement sends this value back to the calling function.

def add(a,b):
  """
  Computes the sum of values a and b
  Returns result

  sample usage:
    ans = add(3,4)
    print(ans) #7
  """
  result = a+b
  return result

Stack Diagrams

A stack diagram is a way to visualize what happens as Python executes your program. Consider the following program:

def square(number):
  toReturn = number*number
  return toReturn

def main():
  x = -9
  squarex = square(x)

  print("%d squared equals %d" % (x,squarex))

main()

Now, on the whiteboard we’ll see how this computation happens in memory. The computer’s memory is where the program stores the state of a running program including the values of all variables and the stack of all functions currently waiting to finish. Here is the general procedure for how a function is run when it is called:

  1. Pause the execution of the current function

  2. Create a stack frame for the called function

    • allocate (place) parameters inside frame

    • allocate local variables for this function here

  3. The value of each argument is copied to the corresponding parameter in order.

  4. Execute called function step-by-step until the return, or end of function

  5. Send back the return value to calling function

  6. Remove or pop the called function off the stack

  7. Continue executing calling function that is now back on top of stack

Some things to keep in mind as you draw your own stack diagrams:

  • Function call stack is on left, values belong on the right

  • The call stack always grows "up" when we call a function

  • The call stack shrinks when a function returns or reaches the end of its body without a return.

  • There is a separate box on the call stack for each function.

  • Parameters point to the same value as the input arguments in the calling function.

  • The assignment operator changes the arrow.

  • A function can only access/reference variable names in its own stack frame. These variables are said to be in the function’s scope

Stack Example 2

def addNumbers(num1,num2):
  total = num1 + num2
  print("In addNumbers:")
  print(num1)
  print(num2)
  print(total)

  #Show the stack diagram as it exists at this point
  return total

def main():

  x = 5
  y = 9

  ans = addNumbers(x,y)
  print("In main:")
  print(ans)
  print(total) #Gives an error. Why?

Answer the following questions:

  • What is the scope, respectively, of x, y, ans, num1, num2, and total?

  • Why does the last line of main() give a runtime error?

Stack Example 3

Try another example of stack drawing.

def absval(x,y):
  if x > y:
    aval = x-y
  else:
    aval = y-x

  # draw stack to this point!
  # as it would look just before return...

  return aval

def main():
  a = 10
  b = 35
  result = absval(a,b)
  print("abs(%d-%d) = %d" % (a,b,result))

main()

Exercise: total

In function_examples.py, define a function total(n), which takes a positive integer as input and returns the sum of the first n positive integers. Then, call your function on several different inputs.