CS51A - Fall 2019 - Class 5
Example code in this lecture
while.py
scores-lists.py
more-lists.py
Lecture notes
prime numbers
- what is a prime number?
- a number that is only divisible by 1 and itself
- what are the first 10 prime numbers?
- the first 100?
- the first 1000?
- How could we write a program that figured this out?
- To start with, how can we tell if a number is prime?
- try and divide it by all of the numbers between 1 and the number
- if none of them divide evenly, then it's prime, otherwise it's not
- A few questions:
- do we need to check all of the numbers up to that number?
- up to 1/2 the number is okay
- really, just need to check up to sqrt(number) (inclusive)
- why? what does it mean if the number has an integer square root?
- how can we check to see if a number divides evenly?
- use the remainder/modulo operator and see if it equals 0 (i.e. no remainder)
- how can we check all of the numbers?
- use a for loop
look at isprime function in
while.py code
- for loop starting at 2 up to the sqrt of the number
- there are multiple versions of the range function
- range with a simple parameter starts counting at 0 up to but not including the specified number
- range with 2 parameters starts counting at the first number up to, but not including, the second number
for i in range(10, 20):
print i
would print out the numbers from 10 - 19 (but not 20)
- the if statement checks to see if the number is divisible by i
- if we find this we can stop early!
- the minute we find this, we know it's not prime so we can return False
- what does "return True" do?
- if we've checked all of the numbers and none of them were divisible (otherwise we would have exited the function with the return False), so return True
- we can use this to see if a number is prime
>>> isprime(5)
True
>>> isprime(6)
False
>>> isprime(100)
False
>>> isprime(101)
True
import math
- A second way to import: import module_name
- To reference a function within that module, you then say module_name.function_name
- Why might we use this option, i.e. when would we use:
from math import *
vs.
import math
- Use the first if you're going to be using the functions a lot and it's clear that they come from that module
- Use the second to be extra clear where the functions are coming from and to avoid naming conflicts
how could we use isprime to print out the first 10 (100, 1000, etc) prime numbers?
- like to do some sort of loop
- will a for loop work?
- we don't know when we're going to stop
- we'd like to keep a count of how many we've seen and only stop when we've reached the number we want
while loop
- another way to do repetition
while <bool expression>:
statement1
statement2
...
statement3
as long as the <bool expression> evaluates to True, it continues to repeat the statements, when it becomes False, it then continues on and executes statement3, etc.
- specifically:
evaluates the boolean expression
- if it's False
- it "exits" the loop and goes on to statement3 and continues there
- if it's True
- executes statement1, statement2, ... (all statements inside the "block" of the loop, just like a for loop)
- go back to beginning and repeat
- how could we use a while loop for our prime numbers problem?
- keep a count of how many primes we've found (initially starts at 0)
- start count from 1 and work our way up
- check each number
- if it's prime
- print it out
- increment the counter of how many primes we've found
- keep repeating this as long as (while) the number of primes we've printed is less than the number we want
can you emulate a for loop with a while loop?
- yes!
for i in range(10):
...
is equivalent to writing:
i = 0
while i < 10:
...
i = i + 1
look at firstprimes function in
while.py code
- current += 1 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
infinite loops
- what would the following code do?
while True:
print("hello")
- 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 selecting "reset shell"
- 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
run
scores-lists.py code
- 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
- lists are a data structure in Python
- what is a data structure?
- a way of storing and organizing data
- lists allow us to store multiple values with a single variable
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 thing in the list is as you'd expect:
>>> type(l[3])
<type 'int'>
storing other 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']
- 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, that is a function that takes a list as a parameter and calculates the average?
- look at the inelegant_average function in
scores-lists.py code
- 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-lists.py code
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
lists are objects and therefore have methods. Any guesses?
- 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)
http://docs.python.org/tutorial/datastructures.html
- 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 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
- 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
- lists are part of a general category of data structures called sequences that represent a sequence of things
- *all* sequences support a number of shared behavior
- the ability to index using []
- the ability to slice using [:]
- a number of built-in functions:
- len
- max
- min
- the ability to iterate over in with a for loop
- We've actually seen one other sequence?
- strings!
strings as sequences
- notice that we can do all the sequence-like things with strings
>>> s = "banana"
>>> s[4]
'n'
>>> s[2:5]
'nan'
>>> len(s)
6
>>> for letter in s:
... print letter
b
a
n
a
n
a
- strings, however, are immutable
>>> s[4] = "c"
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
TypeError: 'str' object does not support item assignment
- no matter how hard you try, you cannot mutate a string
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)
- concatenates 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