Class Notes Week 5


Week 5 Topics

Monday Wednesday Friday


We’ll begin by finishing some exercises we didn’t get to last week:

Writing functions

Recall the general template for writing a function:

def NAME(PARAMATER1, PARAMATER2, ...):
  """
  Purpose
  Parameter description
  Return value description (if any)
  """
  #DO STUFF
  return VALUE #optional

Exercise: Counting Letters

In countLetters.py, I have given the start of the main method which asks the user for a word and a letter to search for. The program will count how many times the given letter appears in the word and output the result.

You will create a function that takes in the user word and chosen letter and returns the number of times the letter appears in the word. For example, the letter l appears three times in the word lollipop. Once you have written your function, call the function from main() and print out the returned result. Here is an example run:

$ cd ~cs21/inclass/w04-functions
$ python3 countLetters.py
Enter word: lollipop
Enter letter: l

There are 3 l's in lollipop

Stack Diagrams

Recall 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
  3. The value of each argument is copied to the corresponding parameter.
  4. Execute called function step-by-step until the return
  5. Send back the return value
  6. Pop the called function off stack
  7. Continue executing calling function that is now back on top of stack

Exercise: Stack diagram

Now, try doing a stack diagram yourself. Show the stack diagram as it would appear at the point in the program noted below. In addition, show the output of the complete program. dir() is a function that prints the name of all variables that are in scope. It is only for diagnostic purposes.

def absval(x,y):

  # What variables are in scope here?
  print(dir())
  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)

  #What variables are in scope?
  print(dir())

  print("abs(%d-%d) = %d" % (a,b,result))

main()

Modifying Parameters

What is the result of modifying the parameter variable for a function? Do the results effect the arguments in the original calling function, or are all changes ignored? The answer depends on the type of the variables and changes.

Take a look at oops_squareFunc.py, which squares the parameter values in a function. What do you think will happen at the end of this program? Test it out and then we will trace through the program to see what happened.

Immutable data types (float,str,int,bool) can never be modified; thus, any changes to the variable require reassigning it a new value. Reassignment breaks any sharing of values between the parameter and its original argument.

Mutable data types are different - they can be modified without reassignment. As an example, we will return to the list datatype and see its methods.

Lists

Lists are a data type in Python that hold a collection of items. Lists are a type of sequence of items. As we will see, many of the methods we use on strings can also be used on lists, since both are sequences. There are two major differences between lists and strings: lists are a sequence of items where the items can be any of any type including (e.g., str, int, etc) while strings are strictly a sequence of characters. The second meaningful difference is that lists are mutable, meaning we can change the contents of the list (strings are immutable).

List operations

We can do similar things to lists as with strings:

An operation that is unique to lists is append(), which adds an item to the list (and thus changes its content)

lst = [0,10,20]
lst.append(30) # adds 30 to lst

We can also iterate over lists just as we did with strings:

for i in range(len(lst)):    # we can iterate over a list
    print lst[i]

Exercise: write a fitness app

In fitApp.py, we will write a fitness app. The program will:

  1. ask the user for a goal (miles run) and number of days to reach goal
  2. use a function (getNumbers()) to obtain the miles run per day and return a list of numbers
  3. use a function to calculate the total progress made (sumList())
  4. output whether the user met their goal

In main(), steps 1 and 4 have been given to you. Together, we will implement step 2, and then you will implement step 3 on your own.

Side effects with mutable parameters

Previously, we showed that reassigning the parameter variable had no effect on the original argument that was sent to the function. This is always the case with immutable data types as once they are created, they cannot be modified.

However, there are circumstances where parameters of mutable data type (e.g., list) can be modified in a function, and the result will have the side effect of also changing the argument variable, despite not returning anything. This can be a desired outcome, or it could be the source of an error in what we want our program to do. Using stack traces to understand this phenomena will help us understand why.

NOTE: in all circumstances, use of the assignment statement resets and connections variables may share (the arrow gets changed to a new location); this applies to lists as well.

Exercise: list modification with side effects

In squareList.py, we will trace through the program and show that, despite not having a return value, our arguments are forever impacted by the call to the function.