20130124
Python provides a number of built-in data structures. The most commonly used one is the list.
A
Python list is an ordered sequence of values. Each value (or
element) in a list can be referenced by its position in the list.
The first position in the list (for no good reason) is position 0.
We can create a Python list in several different ways - the simplest is to specify the values, as in
list_1 = [4,67,23,89]
Each location in a list can be treated as an independent variable, as in
list_1[3] = 47
Printing list_1 at this point would show
[4,67,23,47]
In
fact, since each element of a list can be treated as an independent
variable, the elements of a list do not have to be the same type of
value. For example
list_1[2] = "Greetings, citizen"
print list_1
gives
[4,67,"Greetings, citizen",47]
In fact, the elements of a list can even be other lists.
list_1[0] = ["a",14,"b"]
print list_1
gives
[["a",14,"b"],67,"Greetings, citizen",47]
Lists
differ from simple variables in a crucial way. With a simple
variable the variable name is associated with the location in
memory where the value is stored.. However, with a list variable
the variable name is associated with a location on memory where an address is stored - the address where the first value of the list is stored. In computing, we call this indirect addressing. It is common to refer to the name of the list as a pointer to the list.
This becomes important when we consider code like this:
x = 9 # stores 9 in memory and calls the location x
y = x # copies 9 to another location in memory and calls this location y
x = 4 # stores 4 in the memory location called x
print y # prints 9
list_1
= [4,7,2,8,3] # creates a list
containing 4,7,2,9,3. Stores the location of this list in a
memory location
# and calls this location list_1
list_2
= list_1
# copies the contents of the location called list_1 to a new
location and calls this
#
location list_2
# at this point, list_1 and
list_2 are both pointers to the same list in memory
list_1[2] = 999 # changes the value stored in position 2 of list_1
print list_2 # prints [4,7,999,8,3]
As
you can see, changing one element of list_1 seems to magically change
an element of list_2 as well. Of course what is really happening
is that list_1 and list_2 are both pointing to the same list in memory.
This is called aliasing and it is a frequent cause of errors in our programs.
To create a new list which is a copy of an existing list, rather than becoming an alias, we use what Python calls a slice.
list_1 = [4,7,2,8,3]
list_2
= list_1[:] #
creates a copy of the contents of list_1, stores the copy in memory,
stores the address
#
of the copy in a location, and calls that location list_2
list_1[2]
= 999
# changes the value stored in position 2 of list_1
print list_2 # prints [4,7,2,8,3]
Now
changing an element of list_1 has no effect on list_2 because we made a
completely separate copy of the list using the slice [:]
We can use slicing to make a copy of part of a list. For example
list_1 = [4,7,5,2,8,3,6,1,9]
list_2 = list_1[2:6] # copies positions 2, 3, 4, and 5 of list_1
print list_2 # prints [5,2,8,3]
Notice that the copied slice begins in position 2 and ends in position 5 ... one position before
the end position specified in the [2:6] ... this is consistent with
other aspects of Python. For example, range(10) produces the list
[0,1,2,3,4,5,6,7,8,9] ... the largest value in the range is one less than the value specified.
If we want a slice to start in position 0, we can leave out the 0 in the slice instruction. For example
list_2 = list_1[:5] # is exactly the same as list_2 = list_1[0:5]
If we want a slice to go right to the end of the original list, we can leave out the value after the : . For example
list_2 = list_1[3:] # is exactly the same as list_2 = list_1[3:9]
We
can use negative numbers in the slice indices - these represent
positions counting from the end of the list. A -1 represents the
last position, -2 the second last, etc. So if we want a slice
that contains the last three elements of list-1 we can do this.
list_2 = list_1[-3:]
This
is very useful if we want to make a copy of the last few elements of
the list and we don't know how long the list is.
Actually there is a way to find the length of a list, using the built-in len() function.
x = len(list_1) # the value assigned to x is the number of elements in list_1
We could use len(list_1) in a slice instruction, as in
list_2
= list_1[-3:len(list_1)] # this
does exactly the same thing as list_2 = list_1[-3:]
These are equivalent, but you should probably use list_2 = list_1[-3:] because it is easier to read.