CS21 Week 6: Functions, lists
Monday
Writing functions
Recall the general template for writing a function:
def NAME(PARAMETER1, PARAMETER2, ...):
"""
Purpose
Parameter description(s)
Return value description (if any)
"""
# DO STUFF
# Optional return statement to produce function output
return VALUE
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? We’ll explore this question in more depth this week.
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 introduce the list
datatype.
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 operations 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 (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 (we can re-assign the variable to a different string,
but we can’t change the letters in a string once they’re assigned).
lstA = [3, 4, 5]
lstB = [2.7, 1.4, 3.33]
lstC = ["apple", "orange", "mango"]
List operations
We can do similar things to lists as with strings:
-
+
: concatenation -
len(lst)
: number of items in list -
lst[i]
: index into list to get ith item -
lst * int
: create a list that contains multiple copies of the original list stuck together (works likestr * int
) -
in
: check if a given value is in the list (returns a boolean)
We can use these operators to work with lists much as we did with strings:
repeats = 3
lst = [2, 7] * repeats # equivalent to lst = [2, 7, 2, 7, 2, 7]
for i in range(len(lst)): # iterate over the list
print(lst[i]) # print the i'th element
fruits = ["apple", "orange", "mango"]
if ("apple" in fruits):
print("An apple is a fruit")
See list_examples.py
for more example playing around with lists.
List exercise
Fill in the missing code in squareList-print.py
to complete a program that
squares the items of a list. In that file, main()
prompts the user for input
several times and builds a list out of the input values. Pass that list to
squareList()
, which should iterate over the list and print out the square of
each value in the list.
Challenge
Modify the program so it first asks a user how many numbers they want to square, and then asks for that many values, storing them in a list which is then passed to the function. Hint: how can you create a list of the right length to store these values in?
Wednesday
List Mutability
Another thing we can do with lists that we can’t do with strings is change a single element:
text = "hello"
text[0] = "j" # illegal: Strings are immutable.
lst = [0, 10, 20]
lst[0] = 5 # legal: Changes first element of list.
print(lst)
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.
in all circumstances, use of the assignment operator (= ) resets any
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-inplace.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.
"""
This program takes three values and squares them
"""
def squareListInPlace(nums):
"""
This function squares a list of numbers by mutating the input list.
parameters: the original list
returns nothing; side effect: nums has all values squared
"""
for i in range(len(nums)):
nums[i] = nums[i]**2
def main ():
count = 3
values = [0] * 3
for i in range(count):
values[i] = int(input("Enter value " + str(i) + ": "))
squareListInPlace(values)
print("The squares are %d, %d, and %d" % (values[0], values[1], values[2]))
main()
Exercise: statistical functions
Together, we will write a program, statistics.py
, to get a list of numbers
from the user and then perform several common statistical analysis tasks on
them.
The program should eventually do the following:
-
ask the user how many numbers they want to work with
-
get that many numbers from the user and store them in a list
-
find and display the minimum and maximum values from the list
-
ask the user what they want the adjusted minimum and maximum values to be
-
use functions to modify the list so any value less than the requested minimum gets set to that minimum, and any value greater than the requested maximum gets set to that maximum
-
compute and display the sum-total and the average of the values in the (modified) list
-
instead of using two separate functions to "clamp" the top and bottom of the range to specified min/max values, try writing a single function called
clampRange
to do both at once. This function does not have a stub in the provided file, so you’ll need to figure out what parameters it should have.
A main function and some function stubs for these functions are already present in
statistics.py
; be sure to use an incremental development strategy, meaning
you should write and test one function at a time. Don’t move on to writing
the next function until you’re sure you’ve got the previous ones working.
You’ll also likely want to re-use some of your functions (e.g. the getSum
function can be used by the getAvg
function)
Friday
-
Quiz 2
Pseudorandom Numbers
Python has a random
library that you can import
into your programs and use
to generate random numbers or choices. The actual numbers are pseudorandom,
meaning they are not
truly random. For CS 21
purposes though, they’re random enough.
random Library Synax
First import the random library:
from random import *
Then use one of the various functions in the library. The most useful functions are likely to be:
Function | Description |
---|---|
|
Returns a random float from [0,1). |
|
Randomly choose and return one element from a sequence (e.g., one item from a list). |
|
Chose and return a random number from [start, stop-1]. Like |
|
Shuffle the contents of a list (modifies the list). |
random Examples
To simulate flipping a coin, you could use any of these:
flip = choice(["heads","tails"])
flip = choice("HT")
flip = randrange(2) # assume 0 is heads, 1 is tails
flip = random() # assume < 0.5 is heads
To simulate rolling a 6-sided die:
result = randrange(1,7)
To help decide what to order for dinner:
takeout = ["Pizza", "Wings", "Curry", "Sandwich", "Soup"]
dinner = choice(takeout)
Exercises
-
Finish up the exercises from last class.