CS30 - Spring 2015 - Class 6

Example code in this lecture

   scores-lists.py
   more-lists.py
   higher_order_functions.py

Lecture notes

  • admin
       - class participation
       - assignment 2
       - assignment 3

  • back to our grades program: look at scores-lists.py code
       - there is a function called get_scores. That gets the scores and returns them as a list. How?
          - starts with an empty list
          - uses append to add them on to the end of the list
          - returns the list when the loop finishes
       - average function
          - has a single parameter, but this parameter will represent a list
          - inelegant_average
             - calculates the sum and divides by the number of entries
                - uses a for loop to iterate over the values
                - often, we'll use something besides "i" as a variable name that makes our program more readable
          - is there a better way to do this?
             - look at fancy_average
                - us the sum function over lists
       - median function
          - sorts the values
             - notice again that sort does NOT return a value, but sorts the list that it is called on
          - returns the middle entry

  • What does the sum_list function do in more-lists.py code?
       - takes as input a list
          - what is the type of the list?
             - has to be numbers... result starts out as a number so we can only add other numbers to it
       - sums up all of the numbers in the list
          - result starts out at 0
          - it then iterates through all of the elements in the list and adds it on

  • What does the list_to_string function do in more-lists.py code?
       - takes as input a list
          - what is the type of the list?
             - a list of almost anything!
             - anything that we can call str() on (which turns out to be lots of things)
       - concates all the items in the list into a single string
          - results starts out as the empty string
          - it iterates through each item in the list and concatenates them on to the results
       - this is similar to our example before of summing up all the numbers in a list

  • From strings to lists
       - Remember last time I said that there are a category of things called "sequences"
       - They support a number of shared behaviors:
          - indexing
          - slicing
          - iterating over using for loops
          - asking the length of (using len)
       - Strings are sequences

  • Strings are immutable!
       - Strings and lists share some functionalies
       - However, be careful, they don't share all functionalities
       - Strings are immutable. What does immutable mean?
          - Are not changeable
       - For example:
          >>> some_list = ["a", "b", "c", "d"]
          >>> some_list
          ['a', 'b', 'c', 'd']
          >>> some_list[0] = "car"
          >>> some_list
          ['car', 'b', 'c', 'd']

          >>> fruit = "banana"
          >>> fruit[0] = "a"
          Traceback (most recent call last):
           File "<string>", line 1, in <fragment>
          TypeError: 'str' object does not support item assignment

  • tuples (immutable lists)
       - For a variety of reasons (we'll get into some eventually), we also have immutable lists, called tuples
       - tuples can be created as literals using parenthesis (instead of square braces)
          >>> my_tuple = (1, 2, 3, 4)
          >>> my_tuple
          (1, 2, 3, 4)
          >>> another_tuple = ("a", "b", "c", "d")
          >>> another_tuple
          ('a', 'b', 'c', 'd')

          - notice that when they print out they also show using parenthesis
       - tuples are sequences and support all the functionality that sequences have:
          >>> my_tuple[0]
          1
          >>> my_tuple[3]
          4
          >>> for i in range(len(my_tuple)):
          ...    print my_tuple[i]
          ...
          1
          2
          3
          4
          >>> my_tuple[1:3]
          (2, 3)
       - tuples are immutable!
          >>> my_tuple[0] = 1
          Traceback (most recent call last):
           File "<string>", line 1, in <fragment>
          TypeError: 'tuple' object does not support item assignment
          >>> my_tuple.append(1)
          Traceback (most recent call last):
           File "<string>", line 1, in <fragment>
          AttributeError: 'tuple' object has no attribute 'append'

  • A few cool tricks with tuples
       - unpacking a tuple
          - if we know how many items are in a tuple we can "unpack" it into individual variables
          
          >>> my_tuple = (1, 2, 3)
          >>> my_tuple
          (1, 2, 3)
          >>> (x, y, z) = my_tuple
          >>> x
          1
          >>> y
          2
          >>> z
          3

          - we can also use this feature to assign to multiple variables in one statement:

          >>> (x, y, z) = (10, 11, 12)
          >>> x
          10
          >>> y
          11
          >>> z
          12
          >>> x, y, z = 10, 11, 12
          >>> x, y, z = "apple", "banana", "pineapple"
          >>> x
          'apple'
          >>> y
          'banana'
          >>> z
          'pineapple'

          notice that we can actually leave off the parenthesis and it still does the right thing

       - swapping value in two variables

          >>> x = 10
          >>> y = 20

          - what will the following statement do?

          >>> x, y = y, x

          - evaluate the right hand side giving us the tuple (20, 10)
          - then assign that to the variables x and y

          >>> x
          20
          >>> y
          10

          swapping the values in the two variables!

  • Alternate ways of iterating over lists
       - Write a function called multiply_lists that takes two lists of numbers and creates a new list with the values pairwise multiplied, e.g.

          >>> list1 = [1, 2, 1, 2]
          >>> list2 = [1, 2, 3, 4]
          >>> multiply_lists(list1, list2)
          [1, 4, 3, 8]

       - In words, what would we like to do?
          - Go through the lists at the same time
          - Multiply each element together
          - Append onto a new list

       - How do we go through the lists at the same time?
       - Hint: Here's another way we can iterate through a list

          for item in list:
             print item

          is equivalent to:

          for i in range(len(list)):
             print list[i]

          - in the second example we're iterating of the indices from 0 up to the length of the list - 1 and then indexing into the lists

       - Look at multiply_lists function in more-lists.py code
          - What does the if statement check?
             - make sure they're the same length
          - the for loop then iterates over the indices and multiplies the corresponding ones


  • higher order functions
       - have you ever typed a function into the shell, but forgot the parentheses?
          >>> multiply_lists
          <function multiply_lists at 0x10cd15398>
          >>> abs
          <built-in function abs>

          - Notice that it does NOT give an error
          - Instead, it echoes the value, just like any other expression, in this case, the value is a function!

       - what do the first four function in higher_order_functions.py code do?
          - take two arguments and do standard mathematical calculations

       - what does apply_function do in higher_order_functions.py code?
          - takes three arguments
             - the first is a function!
          - applies the function passed as the first argument to the second and third argument and returns the result

       - functions in python are just like other types of values, e.g. ints, floats, strings, etc
          - we can assign them to variables
             - for example:

             >>> my_abs = abs
             >>> my_abs(-10)
             10
          - we can pass them as parameters
          - we can return them from functions
          - we can even create them on the fly! (more on this later)

       - We can call our apply_function function:
          >>> apply_function(add, 2, 3)
          5
          >>> apply_function(subtract, 2, 3)
          -1

          - to pass a function as a parameter you just give the name of the function as the argument
       
       - def
          - what the keyword def actually does is
             1) create a new function
             2) assign that function to a variable with the name of the function

  • map
       - what does the apply_function_to_list function do in higher_order_functions.py code?
          - takes a function and a list as parameters
             - you can tell that the parameter "function" is a function because we apply it in the line with the append in it
          - iterates through each value in the list
             - applies the function
             - appends the result of the function to a list that is then returned
          - High-level: applies the function to each element in the list and returns a new list containing the result from each of those applications
          - For example:
             >>> apply_function_to_list(double, [1, 2, 3, 4])
             [2, 4, 6, 8]
          - There is actually a built-in function in python that does this called "map"

             >>> map(double, [1, 2, 3, 4])
             [2, 4, 6, 8]

  • filter
       - what does the filter_list function do in higher_order_functions.py code?
          - also takes a function and a list as parameters
          
          - are there any expectations on what the function should do/return?
             - it's used in an if statement
             - it should return a bool, i.e. True or False
          - The filter function is like map in that it applies the function to every element in the list
             - BUT, it only keeps those where the function returns True for that element

          - For example,
             >>> map(is_even, [1, 2, 3, 4])
             [False, True, False, True]
             >>> filter_list(is_even, [1, 2, 3, 4])
             [2, 4]

          - There is actually a built-in function called filter that does exactly what our filter_list function does:
             >>> filter(is_even, [1, 2, 3, 4])
             [2, 4]