Sunday, November 13, 2011

Lists

Python has a special type called a List. A Python list is a set of objects, they could be numbers, or strings, or other objects, enclosed in a pair of brackets, square brackets, [].


The Python range() function is a special function that returns a list object with a sequence of numbers. In our case, we asked for the range 1 to 5, excluding the last number, 5. If you don't specify the first number, the range will start at zero (0).


See that range(3,3) returns an empty list. That's because the end of the range isn't included and since we requested a range from 3 to 3, it's empty. The second range request (range(3,4)) returns a list of only one element, the number 3.

The range() function is commonly found in for loops.


We loop around five times, from 0, to 1, to 2, to 3, to 4. That's five times. In the first loop;

item = 0
value = (1 + 1) * 1 = 2

item = 1
value = (2 + 1) * 2 = 6

item = 2
value = (6 + 1) * 6 = 42

item = 3
value = (42 + 1) * 42 = 1806

item = 4
value = (1806 + 1) * 1806 = 3263442

One thing to remember about the range() function is that it can become inefficient with very large numbers. When used in a loop the way I've created it above, Python constructs  and allocates for a list object. A special type of list object known as a Tuple. We'll discuss this further later.

To find out how many items are in the list, you use the len() function, similar to a string.


Just as with the string object, you can iterate through the list using a for loop.


We added the numbers in the list using a for loop.

You can join two lists together using the "+", concatenation, operator. This is like the string concatenation operator. And just like the string repeat operator, "*", the same operator is used to make copies of lists.


The list "e" is the concatenation of lists "c" and "d". The list "f" is the list "c" repeated twice. This is similar to what we saw with strings.

And just like we saw how we can take slices of strings, we can also take slices of lists. For a comprehensive discussion of what the start and end indices mean, see the discusion on strings. For now, it's enough to say that the first element in the list has the index zero (0), and like strings, we can also count from the end of the list where the last element has the index -1.


a = [1, 2, 3, 4, 5, 6]

The number "1" has the index zero (0). The number "2" has the index 1. And so on. So the slice:

b = a[0:2]

Takes elements from index zero (0) -- the "1", up to and not including the index 2 -- the "3". So the slice becomes [1, 2].

But guess what, unlike strings, lists are mutable! You can change the list elements inline.


This wasn't possible with a string. In the case of strings, trying to change an element in the string by assigning it as:

s[index] = value

would give you an error message.

You can also delete and insert elements into the list. There are two ways to delete elements. The first is to assign an empty list in the position of the elements you want deleted. For example, say you have the list:

a = [1, 2, 3, 4, 5, 6]

and you want to delete the elements, [2, 3]. These are represented by slice a[1:3]. Here's how you do that.


Python also provides a delete function, called del, which makes this easier to see than empty list assignment.


Lastly let's discuss inserting elements into the list. To insert an element into a position in the list, you have to use slice notation. If you don't, unless you're adding elements at the end of the list, you will overwrite the value at the index.

For example, say you have the list:

a = [1, 2, 3, 4, 5, 6]

and you'd like to insert the value zero (0) right after the 3, you'd do the following:


Notice that slice [3:3] selects elements starting at position 3 (currently occupied by the number 4), but doesn't include that position. So, in effect what happens is that the element in that position is shifted over.

What if you wanted to replace the slice [2, 3, 4] with the single zero?


On the left side of the assignment, we selected the slice that includes [2, 3, 4], that's slice [1:4]. We replace that slice with the list [0].

One thing you have to be careful with about lists is copying them. Unlike strings, when you make assignments to lists, an alias is made.

Look at the following example.


Notice what happened. A list "a" was created with three elements, [1, 2, 3]. The variable "b" was set to "a". At this point, a copy of the list "a" wasn't made. "b" is a reference, or an alias, to the existing list created by "a".

So, when the element at index zero (0) is modified by the statement:

b[0] = 4

It's the same element that's referenced by "a". So when we print out the value of "a", we see that the first element, at index zero, has been changed.

How do you make copies?

Take an entire slice of the list.


In this example, we used the slice operator to make a copy of "a". Remember that when you omit the first parameter in the slice it's assumed that you're starting from the first element, and when you omit the last parameter, it's assumed that you're slicing all the way to the end. So, in this case, we're slicing from the first parameter, all the way to the end. Essentially a full copy of the list.

When we make assignments to the list "b" it doesn't affect the list "a" since we now have two separate lists.

Knowing when to slice and when to assign is very important, because when you pass a list item as an argument to a function, a reference to the list item is passed. If the function modifies the elements of the list, the modifications are global.

Here's an example.


In this example we have a list "a" with three elements, [1, 2, 3]. We then define a function delh() that takes a single argument. It's a list argument because in the function body we can see that it deletes the first element and then prints it.

In our example, the first call to the function is:

delh(a[:])

The argument a[:] is a copy of the list "a". The delh() function deletes the first element, and then prints the remaining elements.

Later, out of the function, when we print the values in "a" we see that it's unaffected. It's not changed.

In the second function call to delh() we do the following:

delh(a)

In this case, we're passing a reference to the list. The delh() function deletes the first element and prints the remaining ones. Later, out of the function, when we inspect our original list, "a", we find out that the first element was deleted.

A last word on lists. A couple of useful functions exists to convert strings to lists, and lists to strings.

The first is split. This is a string function that will split a string, based on whitespace, or any string, into a list.

Example:


In the first example, the list "l" is created using the following line:

l = string.split(s)

Because we haven't specified how to split the string, Python splits it based on whitespace. So we get a list of the words.

In the second split command,

ll = string.split(s, 's')

We instruct Python to split the string at each occurrence of the string, or letter, "s". The "s" won't be included in the result, but spaces will.

Now, if you have a list of elements, you can create a string using the "join" function.


In the first join statement, since we haven't instructed Python how we'd want the list join performed, Python joins the elements of the list using a single space. However, in the second example, we ask Python to join the elements using the string "::", two colons.

This has been a fairly long section on lists. The next one is very short, because most of the material covering lists also pertains to that special type of a list, called a Tuple.

No comments:

Post a Comment