The assignment operator does NOT create a new list. Rather it creates a new name for an existing list:
>>> L1 = [ 'cat', 'dog', 'ant', 'tiger', 'parrot' ]
>>> L2 = L1
>>> L1
['cat', 'dog', 'ant', 'tiger', 'parrot']
>>> L2
['cat', 'dog', 'ant', 'tiger', 'parrot']
>>> L1[2] = 'hawk'
>>> L1
['cat', 'dog', 'hawk', 'tiger', 'parrot']
>>> L2
['cat', 'dog', 'hawk', 'tiger', 'parrot']
Surprised? This is called an alias. Compare it with:
>>> S1 = 'this is a string'
>>> S2 = S1
>>> S1 = 'I changed the first string'
>>> S1
'I changed the first string'
>>> S2
'this is a string'
Python is designed to do this primarily for reasons of efficiency since
If we want to copy a list we should use a special set of methods. We’ll see those next.
When lists are passed to functions, the parameter becomes an alias for the argument in the function call.
Here is an example of a function that returns a list containing the two smallest values in its input list:
def smallest_two(mylist):
mylist.sort()
newlist = []
if len(mylist) > 0:
newlist.append(mylist[0])
if len(mylist) > 1:
newlist.append(mylist[1])
return newlist
values = [35, 34, 20, 40, 60, 30]
print "Before function:", values
print "Result of function:", smallest_two(values)
print "After function:", values
In class we will discuss what happened
Recall
>>> co2_levels = [ 320.03, 322.16, 328.07, 333.91, 341.47,
348.92, 357.29, 363.77, 371.51, 382.47, 392.95 ]
Now suppose we just want the values at indices 2, 3 and 4 of this in a new list:
>>> three_values = co2_levels[2:5]
>>> three_values
[328.07, 333.91, 341.47]
>>> co2_levels
[ 320.03, 322.16, 328.07, 333.91, 341.47, 348.92, 357.29, 363.77,
371.51, 382.47, 392.95 ]
We give the first index and one more than the last index we want
If we leave off the first index, 0 is assumed, and if we leave off the last index, the length of the list is assumed.
Negative indices are allowed — they are just converted to their associated positive values. Some examples:
>>> L1
['cat', 'dog', 'hawk', 'tiger', 'parrot']
>>> L1[1:-1]
['dog', 'hawk', 'tiger']
>>> L1[1:-2]
['dog', 'hawk']
>>> L1[1:-4]
[]
>>> L1[1:0]
[]
>>> L1[1:10]
['dog', 'hawk', 'tiger', 'parrot']
The most general form of slicing involves three values
L[si:ei:inc]
where
Any of the three values is optional
We’ll work through some examples in class to
Note: L[:] returns a copy of the whole list of L. This is the same using function list(L):
>>> L2 = L1[:]
>>> L2[1] = 'monkey'
>>> L1
['cat', 'dog', 'hawk', 'tiger', 'parrot']
>>> L2
['cat', 'monkey', 'hawk', 'tiger', 'parrot']
>>> L3 = list(L1)
>>> L3[1] = 'turtle'
>>> L1
['cat', 'dog', 'hawk', 'tiger', 'parrot']
>>> L2
['cat', 'monkey', 'hawk', 'tiger', 'parrot']
>>> L3
['cat', 'turtle', 'hawk', 'tiger', 'parrot']
Concatenation:
>>> v = [1,2,3]+[4,5]
>>> v
[1,2,3,4,5]
Replication:
>>> [1]*3
[1,1,1]
These are very similar to the analogous operations with strings.
What is the output of the following?
x = [6,5,4,3,2,1] + [7]*2
y = x
x[1] = y[2]
y[2] = x[3]
x[0] = x[1]
print x
y.sort()
print x
print y
Write a command to extract values from a list L0 indexed by 0,1,4,7 and 10,11, and return a list containing only these values.
Write a slicing command to extract values from a list L0 indexed by 1, 4, 7, 10, etc.
Despite the presence of a number of list methods, we need to be able to invent new operations that we can apply to lists.
This requires the notion of a “loop” where we apply a computation to each item in a list.
As an example, here is code to compute the average CO level, as it would appear when typing directly into the Python interpreter:
animals = ['cat', 'monkey', 'hawk', 'tiger', 'parrot']
all_animals = ""
index = 1
for value in animals:
all_animals += "%d. %s\n" %(index, value.capitalize())
index += 1
print all_animals
We can understand what is happening by looking at this piece-by-piece:
Try the following code. Let’s discuss what we have learnt from this:
L1 = ['cat', 'dog', 'hawk', 'tiger', 'parrot']
for value in L1:
value = 'sheep'
print L1
Write a program to find the number of values greater than the average for the co2_levels given in the following list. Also, print the median of the values that are greater than average.
co2_levels = [ 320.03, 322.16, 328.07, 333.91, 341.47, \
348.92, 357.29, 363.77, 371.51, 382.47, 392.95 ]
Some functions do NOT return a value:
What happens when you try to assign or print the value of a function that does not return anything?
>>> t = [1, 5, 3 ]
>>> u = t.sort()
>>> print t
>>> print u
Moral of the story: if a function does not return a value, do not try to use its return value!!
Version 1: use the function list to create a list of the characters in the string:
>>> s = "Hello world"
>>> t = list(s)
>>> print t
['H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
Use the string split function, which breaks a string up into a list of strings based on the character provided as the argument.
We will play with the s = "Hello world" example in class.
What happens when we type the following?
>>> s = "Hello world"
>>> t = list(s)
>>> s1 = str(t)
This is unlikely to achieve what we want, which is usually the concatention of all of the strings in the list (assumming they are strings).
We will solve this problem using a for loop in the next exercise.
We can index strings:
>>> s = "Hello, world!"
>>> print s[5]
,
>>> print s[-1]
!
We can apply all of the slicing operations to strings to create new strings:
>>> s = "Hello, world!"
>>> s[:len(s):2]
'Hlo ol!'
Unlike lists, however, we can not use indexing to replace individual characters in strings:
>>> s[4] = 'c'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
Suppose you have the string
>>> s = "cat | dog | mouse"
and you’d like to have the list of strings
>>> L = [ "cat", "dog", "mouse"]
Splitting the list alone does not solve the problem. Instead, you need to use a combination of splitting, and a loop that strips off the extra space characters from each string and appends to the final result. Write this code. It should be at most 4-5 lines of Python.
Lists can contain any mixture of values, including other lists.
For example, in
>>> L = [ 'Alice', 3.75, ['MATH', 'CSCI', 'PSYC' ], 'PA' ]
We will write code to print the courses, to change the math course to a stats course, and to append a zipcode.
Let us create a program to send fancy “Thank you” notes to all our relatives who have given us gifts recently.
We’ll start by making a list of lists:
gift_list = [['Uncle John', 'skateboard'], \
['Aunt Marie', 'Amazon gift card'], ['Mr. Idle', 'backpack']]
Now we’d like a function that takes a name and a gift and prints a fancy output that might look something like:
Dear Uncle John,
Thank very much for your gift of a skateboard.
I will enjoy using it very much. I hope you
are doing well.
Sincerely,
John Cleese
This function should have as arguments, the name of the giver, the name of the gift, and the gift recipient (you), e.g.
def print_thank_you( giver, gift, recipient ):
Once we write this function, we will write a for loop to print all of the thank yous.
The result will be posted on the course web site.
Given a list
>>> L = [ 'cat', 'dog', 'tiger' ]
write a line of code to append the string 'lion'
Rewrite L so that it is a list of lists, with household pets in the 0th (sub)list, zoo animals in the first.
How can you append an additional list of farm animals (e.g. 'horse', 'pig' and 'cow') to L.
Write code to remove 'tiger' from the sublist of zoo animals.
Without typing into the Python interpreter, find the outputs from the following operations:
>>> x = ['a','b','c','d', 'e']
>>> print x
>>> for item in x:
... print "*%s*" %item,
...
>>> print x[3]
>>> x[3] = 3
>>> x
>>> len(x)
>>> x[2]=x[1]
>>> x
>>> x[5]
>>> y = x[1:4]
>>> y
>>> x
What about these operations?
>>> y = [1, 2, 3]
>>> y.append('cat')
>>> y
>>> y.pop()
>>> y
>>> y.remove(2)
>>> y
>>> y.remove('cat')
>>> z = ['cat','dog']
>>> z.insert(1,'pig')
>>> z.insert(0,'ant')
>>> z
>>> z.sort()
>>> z
>>> z1 = z[1:3]
>>> z1
>>> z
Write a function that returns a list containing the smallest and largest values in the list that is passed to it as an argument without changing the list? Can you think of ways to do this with sorting and without? Hint: use a for loop.