ListsΒΆ

Lists provide a way to represent ordered sequences of data. They are an essential part of programming in Python and you will use them repeatedly in your work. The items in a list, also known as the elements of the list, do not need to have the same type.

Literals

List literals are written using square brackets with the individual elements separated by commas. The empty list is written as []. Here are some examples taken from an iPython session:

In [1]: l0 = []

In [2]: l1 = [1, "abc", 5.7, [1, 3, 5]]

The variable l0 refers to an empty list. The variable l1 refers to a list with four elements: an integer, a string, a floating point number, and a list.

Length

You can find the length of a list using the len function. The expression len(l0), for example, will evaluate to 0 and the expression len(l1) will yield the value 4.

Indexing

When used in an expression, the indexing operation ([]) is used to retrieve the value of the ith element of a list. That is, given a list l, the expression l[i] will evaluate to the value of the ith element of the list. Here are some examples uses of the indexing operation:

In [3]: l1[0]
Out[3]: 1

In [4]: l1[1]
Out[4]: 'abc'

In [5]: l1[3]
Out[5]: [1, 3, 5]

Notice that we use zero to get the first element of the list and that the last element in a list, l, is at index len(l)-1. All indexing is zero-based in Python.

Lists are mutable, that is, we can change them. To change the value at index i in list l, you simply put l[i] on the left-hand side of an assignment statement. For example:

In [35]: l1[2] = "xyz"

In [36]: l1
Out[36]: [1, 'abc', 'xyz', [1, 3, 5], 27]

Notice that the statement x1[2] changes the value of at index 2, to be the string "xyz"

Debugging hint: Forgetting about zero-based indexing is the source of two kinds of problems in Python: (1) retrieving the second element when you want the first and (2) indexing beyond the end of the list in an attempt to get the last item in the list. The first of these problems can be difficult to track down, because your program will not fail at the point of the error. In fact, it may not fail at all! The second problem will cause your program to fail, which can be frustrating, but at least you know there is a problem!

While these examples all use integer literals (0, 1, etc), any expression that yields an integer can be used to describe the index for a list. The expression is evaluated to yield an integer that is then used to index into the list. For example:

In [9]: i = 0

In [10]: l1[(i+1)*2]
Out[10]: 5.7

In [13]: l2 = [1, 0, 3, 2]

In [12]: l1[l2[3]]
Out[12]: 2

In [13]: l1[l2[3]] = 5.7

In [14]: l1
Out [14]: [1, 'abc', 5.7, [1, 3, 5], 27]

The first example is straightforward. The second is a bit more complex: the expression l2[0] yields the value 2, which is then used to index into the list l1, which yields the string "xyz". The third statement changes the value of l1 at index 2 back to 5.7.

The result of indexing into a list could yield a value that itself may be a list, which can be indexed into like any other list:

In [6]: l1[3][0]
Out[6]: 1

Slicing

In addition to getting a single value from a list, it can be useful to extract a copy of a sub-list from a list. The slicing operation (:) is used for this purpose. The expression l1[1:3], for example, yields a new list with the value ['abc', 5.7]. Notice that the slice yields the elements from indices up to but not including the upper bound. To make a copy of a list l, of length N, you can use the expression l[0:N].

The expression on either side of the colon (e1 : e2) or even both expressions can be left out. The default value for the first expression (e1) is 0. The default value for the second expression is the length of the list. Here are some example uses of slicing:

In [15]: l1[1:3]
Out[15]: ['abc', 5.7]

In [16]: l1[:3]
Out[16]: [1, 'abc', 5.7]

In [17]: l1[1:]
Out[17]: ['abc', 5.7, [1, 3, 5]]

In [18]: l1[:]
Out[18]: [1, 'abc', 5.7, [1, 3, 5]]

Useful operations on lists

The equality operator (==) signifies value equality in Python. For lists, that means that two lists are deemed to be equal if they hold the same values in the same order. For example, evaluating the expression [1, 2, 3] == [1, 2, 3] will yield the value True, while evaluating the expression [1, 2, 3] == [] will yield the value False.

The append method is used to add a new element to the end of an existing list. It is important to note that this operation changes the value of the list. For example, after executing the statement l1.append(27), l1 will have the value [1, 'abc', 5.7, [1, 3, 5], 27] You’ll notice that this statement uses somewhat unusual syntax: rather than looking like a function call, the name of the method (preceeded by a dot) comes after the list! We will explain this notation in detail later in the term. For now, just remember that appending elements to a list changes the list and uses a somewhat odd notation.

The concatenation operation (+) creates a new list from two existing lists. For example:

In [25]: l3 = [1, 2, 3]

In [26]: l4 = ['a', 'b', 'c']

In [28]: l5 = l3 + l4

In [29]: l5
Out[29]: [1, 2, 3, 'a', 'b', 'c']

In [30]: l5[2] = 7

In [31]: l5
Out[31]: [1, 2, 7, 'a', 'b', 'c']

In [32]: l3
Out[32]: [1, 2, 3]

Notice that the update to l5 does not change the value of l3, because l5 is a new list that has copy of the values from l3 followed by a copy of the values from l4.

At times, you will want to create a list of a specific size with some initial value. You could do this task with a loop, but the concatenation mechanism provides a useful shorthand. Given a list l and a value n, the expression l*n concatenates n copies of the list l into a new list. (If this notation seems odd, recall that multiplication is just repeated addition.) For example, the expression [0]*10 creates a list of length 10 with of all zeros and the expression [False]*len(l7) creates a list that has the same length as l7 and in which every element has the value False. Notice that in this second example, the number of copies is determined by evaluating the expression len(l7).