Week 4: Functions

Week 4 Goals

  • Learn how the choice function can pick random values

  • Learn to write your own functions

  • Learn how function call arguments are passed to function parameters

  • Learn to use the return statement to send a value back to the calling function

  • Learn to how python uses a call stack to keep track of function calls

  • Learn about variable scope and how it relates to the call stack

Get Week 4 In-class Code

To copy over the week 4 in-class example programs, do the following (If you have trouble with either of these steps, ask a Ninja or your professor for help):

  1. Create a w04-functions subdirectory in your cs21/inclass directory, and cd into it:

    $ cd ~/cs21/inclass
    $ mkdir w04-functions
    $ cd w04-functions
    $ pwd
    /home/yourusername/cs21/inclass/w04-functions
  2. Copy over the week 4 files into your w04-functions subdirectory (check that they copied successfully copied by running ls:

    $ cp ~admin21/public/w04-functions/*.py ./
    $ ls
    function_examples.py guess.py print_format.py rectangle.py while_loops.py

Week 4 Code

  • print_format.py: Some extra print formatting examples. Shows input with prompt variable

  • guess.py: Using the choice function with a while loop

  • function_examples.py: Examples of defining and calling functions

  • rectangle.py: A program that uses functions to compute the area and perimeter of a rectangle

  • while_loops.py: More while loop examples that use functions

String Formatting

The print statement is nice for outputting, but it is difficult to format the output in a way we prefer. For example, every time we put out a dollar amount, we can’t guarantee two digits after the decimal point for the cents and we also have to always leave a space between the dollar sign and the amount. String formatting allows us to define string templates:

%s

string value

%d

int value

%f

float value

String formatting also enables optional width and precision values:

Feature Syntax Example Semantics

width

%<number>type

%10s

Format a number to a string with ten spaces minimum.

precision (float only )

%.<number>f

%.2f

Require exactly two digits after a decimal point.

Let’s look at some of the examples in print_format.py that show printing out the float variable pi from the math library using different formatting. This also shows some other examples.

Note that you can combine multiple values in a single string format:

item = "dozen eggs"
qty = 4
price = 2.49
print("%d %s cost $%.2f" % (qty, item, qty*price) )

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:

  • Modularity and Readability: break program up into functional parts, make programs easier to read/understand/debug.

  • Abstraction: hide low-level details of a function until you need to understand them; you can use a function without having to know how it is implemented (e.g., the print function).

  • Code Reuse: put repeated code into functions: "write code once, use function multiple times".

  • Minimize programmer error: write and test functions in isolation.

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 passing the 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)

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 reads in 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

    a: (int/float) first value
    b: (int/float) second value

    Returns: (int/float) sum of a and b

    sample usage:
        ans = add(3, 4)
        print(ans)        # Should print: 7
    """

    result = a + b
    return result

Stack Diagrams

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


def main():
  a = 6
  b = 11
  avg = average(a,b)

  print("The average of %d and %d equals %.1f" % (a, b, avg))

def average(num1, num2):
  """
  computes the average of two numeric values
    param num1: one value
    param num2: the other value
    returns: the average of the two values
  """

  to_return = (num1 + num2)/2

  return to_return

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 execute when called:

  1. Pause the execution of the current function.

  2. Create a stack frame for the called function.

    • space for parameters are allocated in the function’s stack frame

    • space for local variables are allocated in the function’s stack frame

  3. Each argument’s value is passed to the corresponding parameter: the value of each argument (the reference in the box) is copied to the corresponding parameter in order. For example, the third parameter refers to the same value of as the third argument.

  4. Execute called function step-by-step until the return or until it reaches the end of the function body.

  5. Send back the return value to calling function.

  6. Remove or pop the called function’s frame off stack.

  7. Continue executing calling function that is now back on top of stack. (the called function now evaluates to its return value in the caller)

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

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

  • Space for variables and parameters are inside stack frames, the values to which they refer are outside the stack

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

  • The call stack shrinks when a function returns.

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

  • Parameters point to the same value as the 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

Try: Stack Example 2

def main():

  x = 5
  y = 9

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

def add_numbers(num1,num2):
    """
    adds two numbers together
      param num1: one value
      param num2: the other value
      returns: sum of num1 and num2
    """

    total = num1 + num2
    print("In add_numbers:")
    print(num1)
    print(num2)
    print(total)

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

main()
  1. Draw the stack up to the point right before return total is executed

  2. Answer the following questions:

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

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