Lecture 5: While and Lists

Topics

Looping with While

  • look at firstprimes function in while.py
    • every time through the loop we increment the number we're examining
    • if that current number happens to be prime, we increment count
    • the loop continues "while" count < num, that is as long as the number we've found is less than the number we're looking for
  • Puzzle: While: implement is_power_of_two using only multiplication and ==

Infinite Loops

  • What will this do?

    while True:
        print("hello")
    
  • It will never stop!
    • in this case you should see some output
    • sometimes, it will look like the program just froze if you're not actually printing anything out
  • you can stop this by hitting the "Rerun" button (a square with a looped arrow) in the Python Console, or hit the square "Stop" button.
  • be careful about these with your program. They're called an infinite loop.
  • if you think you might have an infinite loop
    • put in some print statements to debug
    • think about when the boolean expression will become False and make sure that is going to happen in your loop

Lists

  • Check out scores_lists.py
  • First, prompts the user to enter a list of scores one at a time
    • how is this done?
      • while loop
      • what is the exit condition?

        • checks to see if the line is empty
        while line != "":
        
  • then, calculate various statistics based on what was entered
  • how are we calculating these statistics?
    • average?
      • could keep track of the sum and the number of things entered
      • divide at the end
    • max?
      • keep track of the largest seen so far
      • each time a new one is entered, see if it's larger, if so, update the largest
    • min?
      • same thing
    • median?
      • the challenge with median is that we can't calculate it until we have all of the scores
      • need to sort them and then find the middle score
  • why can't we do this using int/float variables?
    • we don't know how many scores are going to be entered
      • even if we did, if we had 100 students in the class, we'd need 100 variables!
  • lists are a data structure in Python
    • what is a data structure?
      • a way of storing and organizing data
      • not just an atomic type like int or float, but an aggregate
  • lists allow us to store multiple values with a single variable
    • (in a sense, strings are like this too—how?)

creating lists

  • we can create a new list using square brackets

    >>> [7, 4, 3, 6, 1, 2]
    [7, 4, 3, 6, 1, 2]
    >>> 10 # not a list
    10
    >>> [10]
    [10]
    >>> l = [7, 4, 3, 6, 1, 2]
    >>> l
    [7, 4, 3, 6, 1, 2]
    >>> type(l)
    <type 'list'>
    
  • lists are a type and represent a value, just like floats, ints, bools and strings. We can assign them to variables, print them, etc.
  • what do you think [] represents?
    • empty list
>>> []
[]

accessing lists

  • we can get at particular values in the list by using the [] to "index" into the list

    >>> l = [7, 4, 3, 6, 1, 2]
    >>> l[3]
    6
    
    # notice that indexing starts counting at 0, not at 1!
    
    >>> l[0]
    7
    
  • What do you think l[20] will give us?

    >>> l[20]
    Traceback (most recent call last):
     File "<string>", line 1, in <fragment>
    IndexError: list index out of range
    
    • we can only index from 0 up to the length of the list minus 1
  • What do you think l[-1] will give us?

    >>> l[-1]
    2
    
    • if the index is negative it counts back from the end of the list
  • notice that the type of the thing the list is as you'd expect:

    >>> type(l[3])
    <type 'int'>
    

storing things in lists

  • draw the list representation
  • a list is a contiguous set of spaces in memory
    • [ _ , _ , _ , _ ]
  • we can store anything in each of these spaces

    >>> ["this", "is", "a", "list", "of", "strings"]
    ['this', 'is', 'a', 'list', 'of', 'strings']
    >>> list_of_strings = ["this", "is", "a", "list", "of", "strings"]
    >>> list_of_strings[0]
    'this'
    >>> [1, 5.0, "my string"]
    [1, 5.0, 'my string']
    >>> l = [1, 5.0, "my string"]
    >>> type(l[0])
    <type 'int'>
    >>> type(l[1])
    <type 'float'>
    >>> type(l[2])
    <type 'str'>
    
  • In general, it's a good idea to have lists be homogeneous, i.e. be of the same type

slicing

  • sometimes we want more than just one item from the list (this is called "slicing")
  • We can specify a range in the square brackets, [], using the colon (:)

    >>> l = ["this", "is", "a", "list", "of", "strings"]
    >>> l[0:3]
    ['this', 'is', 'a']
    >>> l[1:5]
    ['is', 'a', 'list', 'of']
    >>> l[1:1]
    []
    >>> l[-3:-1]
    ['list', 'of']
    
    • slicing generates a new list
    • that includes the items from the list starting at the first number and up to, but not including, the second number

looping over lists

  • We can use the for loop to iterate over each item in the list:

    >>> my_list = [4, 1, 8, 10, 11]
    >>> for value in my_list:
    ...    print(value)
    ...
    4
    1
    8
    10
    11
    
    • This is often called a "foreach" loop, i.e. for each item in the list, do an iteration of the loop
  • write a function called sum that sums up the values in a list of numbers

    def sum(numbers):
       total = 0
       for val in numbers:
          total += val
    
       return total
    
  • back to our stats program… how could we write average given what we know so far? average should be a function that takes a list as a parameter and calculates the average.
  • look at the inelegant_average function in scores_list.py

    • loop over each of the elements in the list
      • accumulate a sum
      • accumulate a count
      • divide the sum by the count

built-in functions over lists

  • there are also some built-in functions that take a list as a parameter
  • we can get the length of a list

    >>> len(l)
    3
    >>> len([1, 2, 3, 4, 5])
    5
    >>> len([])
    0
    
  • max

    >>> l = [5, 3, 2, 1, 10]
    >>> max(l)
    10
    
  • min

    >>> min(l)
     1
    
  • sum

    >>> sum(l)
    21
    
  • and many others!

methods on lists

  • lists are objects and therefore have methods
  • (remember: methods are like associated functions, e.g. "hello".capitalize())
  • append: add a value on to the end of the list

    >>> my_list = [15, 2, 1, 20, 5]
    >>> my_list.append(100)
    >>> my_list
    [15, 2, 1, 20, 5, 100]
    
    • notice that append does NOT return a new list, it modifies the existing list!
  • We can look at the documentation do see what is available
>>> help([])
>>> help(list)
  • pop: remove a value off of the end of the list and return it

    >>> my_list.pop()
    100
    >>> my_list
    [15, 2, 1, 20, 5]
    
    • notice that it both modifies the list and returns a value
    • if you want to use this value, you need to store it!

      >>> x = my_list.pop()
      >>> x
      5
      
    • pop also has another version where you can specify the index

      >>> my_list = [15, 2, 1, 20, 5]
      >>> my_list.pop(2)
      1
      >>> my_list
      [15, 2, 20, 5]
      
    • insert: inserts a value at a particular index

      >>> my_list = [15, 2, 1, 20, 5]
      >>> my_list.insert(2, 100)
      >>> my_list
      [15, 2, 100, 1, 20, 5]
      
      • again, lists are mutable, so insert does not return a new list, but modifies the underlying one
    • sort

      >>> my_list = [15, 2, 1, 20, 5]
      >>> my_list.sort()
      >>> my_list
      [1, 2, 5, 15, 20]
      >>> my_list = ["these", "are", "some", "words", "to", "sort"]
      >>> ["these", "are", "some", "words", "to", "sort"].sort()
      >>> my_list = ["these", "are", "some", "words", "to", "sort"]
      >>> my_list.sort()
      >>> my_list
      ['are', 'some', 'sort', 'these', 'to', 'words']
      

Back to scores_list.py

  • 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 (it accumulates them)
    • returns the list when the loop finishes
  • 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

lists are mutable

  • what does that mean?
    • we can change (or mutate) the values in a list
  • notice that many of the methods that we call on lists change the list itself
  • we can mutate lists with methods, but we can also change particular indices

    >>> my_list = [15, 2, 1, 20, 5]
    >>> my_list
    [15, 2, 1, 20, 5]
    >>> my_list[2] = 100
    >>> my_list
    [15, 2, 100, 20, 5]
    

Sequences besides lists

  • Lists are series of things
    • so are strings (but not mutable!)
  • common behavior of sequences
    • indexing with []
    • slicing (also with [])
    • len, max, sum, and some other built-in functions
    • can use for-each loop #+BEGIN_src python

for character in "hello": print("h") #+END_src python

Tuples

  • Tuples are a lot like lists
    • but once you've made one, you can't change it
  • tuples can be created as literals using parentheses (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 parentheses
  • tuples are sequences and support all the functionality that sequences have:

    >>> my_tuple[0]
    1
    >>> my_tuple[3]
    4
    >>> for val in my_tuple:
    ...    print(val)
    ...
    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'
    
  • destructuring assignment ("unpacking")
    • 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
    • destructuring works for tuples but also for lists (and all other sequences!)

Iterables and Iterators

  • iterables/iterators
    • iterating over elements, show for loops again
      • iterating over lists of tuples, for variable as destructuring pattern

        for (fruit, number) in [('apple', 1), ('banana', 2), ('cherry', 3)]:
            print("Fruit number "+str(number)+" is "+fruit)
        
    • much preferred over indexes
    • indexing ok with multiple lists

Author: Joseph C. Osborn

Created: 2020-04-21 Tue 10:44

Validate