Class Notes Week 4


Announcements

Week 4 Topics

Monday Wednesday Friday


Academic Integrity

Here is a page on Academic Integrity In particular, note that Discussing ideas and approaches to problems with others on a general level is fine (in fact, we encourage you to discuss general strategies with each other), but you should never read anyone else's code or let anyone else read your code.

Please get in the habit of not reading anyone else's code or letting anyone else read your code.

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:

as well as optional width and precision values

An example, if we print out the float variable pi from the math library:

>>> from math import pi
>>> print(pi)
3.14159265359
>>> print("Pi is %f|" % (pi))
Pi is 3.141593|
>>> print("Pi is %.2f|" % (pi))
Pi is 3.14|
>>> print("Pi is %20.2f|" % (pi))
Pi is                 3.14|
>>> print("Pi is %-20.2f" % (pi))
Pi is 3.14                |

You can combine multiple templates in a single string format:

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

Exercise: currency.py, wheels.py

  1. Rewrite your currency program currency.py from Lab 01 to use 2 digits after the decimal place. To start with your submission, copy the file over:
$ cd
$ cd cs21/inclass/w04-functions-while
$ cp ../../labs/01/currency.py .
$ atom ./
  1. Write a program in wheels.py that uses string formatting to nicely write out lyrics to the children's song The Wheels on the Bus
item = "wheels"
verb = "go"
action = "round and round"
print("The %s on the bus %s %s" % (item, verb, action))

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:

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.

As an initial example, let's return to wheels.py and try to define a function that prints each verse of the song.

def verse(item, verb, sound):
  # print out the verse
  print("The %s on the bus %s %s," % (item, verb, sound))
  print("%s, %s" % (sound, sound))
  print("The %s on the bus %s %s, all through the town" % (item, verb, sound))

Once a function is defined, you can call the function, by giving the name of the function and specific values for each parameter. Here is how to call our verse function for The Wheels on the Bus:

verse("Wheels", "go", "round and round")

Exercise: practice function definition and calls

Practice defining and calling functions by modifying your program in wheels.py to print out lyrics to the song, by using the verse(...) function. First, define the verse() function. Then, use it by calling verse() once for each verse of the song.

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 sum(n) to add the first n integers, you'll probably want to define and return an accumulator variable (say totalSum). Then, once you've added the numbers, the return totalSum statement gives this value back to the calling function.

Exercise: more practice with function definition and calls.

Practice defining and calling functions by modifying your function_examples.py program.

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, associate them with parameters of the called function.
  3. Execute called function using those values.
  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.

verse("Mathematicians", "count", "%d, %d, %d"%(1,2,3))
x = -19
absx = absValue(x)
print("The absolute value of %d equals %d." % (x, absx))

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
  toReturn = toReturn * number
  return toReturn

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

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

main()

Now, on the whiteboard we'll see how this computation happens in memory.

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

Exercise:

Open the program stack_diagram.py and trace through the program's execution by drawing a stack diagram.


Recap

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:

Steps that occur when a function is called:

  1. Suspend Current Function.
  2. Evaluate Arguments, associate them with parameters of the called function.
    1. Create a stack frame for the called function
    2. allocate (place) parameters inside frame
    3. allocate local variables for this function here
    4. The value of each argument is copied to the corresponding parameter in order.
  3. Execute called function using those values.
  4. Return back to the calling function.
    1. send back the return value to calling function
    2. remove "pop" the called function off stack
    3. 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:

Stack Example 2

def multNumbers(num1,num2):
  total = num1 * num2
  print("In multNumbers:")
  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 = multNumbers(x,y)
  print("In main:")
  print(ans)
  print(total) #Gives an error. Why?

Answer the following questions:

Stack Example 3

Try another example of stack drawing.

def absDiff(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 = absDiff(a,b)
  print("abs(%d-%d) = %d" % (a,b,result))

main()

While loops

Taking a break from functions for a bit we will introduce yet another syntactic tool for designing programs in python: the while loop. You have previously seen the for loop, Boolean types, and the if statement. The while loop is a mix of these three concepts. 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.

Look at some examples in while_loops.py