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 != "":
- how is this done?
- 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
- average?
- 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!
- we don't know how many scores are going to be entered
- 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
- what is a data structure?
- 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 numbersdef 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
- look at the average function in scores_list.py
- loop over each of the elements in the list
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
- sorts the values
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
- indexing with
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
- iterating over elements, show for loops again