Lists#

Previous sheets only showed very simple “types” of data in Python: integers, floating point numbers, and strings. A great deal of programming involves manipulating different combinations of these data types. In order to do so, we often store them in data structures. The simplest of these data structures is the list. A list is precisely what it claims to be: a sequence of objects in some order.

my_first_list = ["apple", 3, "banana", 4.2]

The variable my_first_list now contains 4 objects: 2 strings, an integer, and a float. We can store any object in a list, including some things you might not necessarily think of as objects. For example, in Python functions are objects, so we can store functions in lists!

import numpy as np
my_function_list = [np.sin, np.cos, np.tan]

We can add things to the end of a list:

my_first_list.append(23)
my_first_list
['apple', 3, 'banana', 4.2, 23]

And we can remove things from a list:

my_first_list.remove(4.2)
my_first_list
['apple', 3, 'banana', 23]

In order to access the elements of the list, we use square brackets:

my_first_list[0]
'apple'

Important note: the first element of a list has index 0! This is a very common source of errors.

my_first_list[3]
23

We can also count from the end using negative numbers; this can be very convenient!

my_first_list[-1]
23

To check whether an element is in a list, you can use in:

"banana" in my_first_list
True

To create an empty list, use []:

empty_list = []

You can get the length of a list using len:

len(my_first_list)
4

We could use len to help us loop through a list:

for i in range(len(my_first_list)):
    print(f"my_first_list element {i}: {my_first_list[i]}")
my_first_list element 0: apple
my_first_list element 1: 3
my_first_list element 2: banana
my_first_list element 3: 23

However, Python provides a more elegant way of looping through a list; in general it has the form

for x in some_list:
    loop body
statements to run after loop
L = []
for x in my_first_list:
    L.append(x * 3)  # this will multiply numbers by 3, and repeat strings 3 times
L
['appleappleapple', 9, 'bananabananabanana', 69]

If you want to loop through the elements of a list and their positions at the same time, use enumerate:

for i, x in enumerate(my_first_list):
    # i will refer to the position in the list, x to the element
    print(f"my first list, element {i}: {x}")
my first list, element 0: apple
my first list, element 1: 3
my first list, element 2: banana
my first list, element 3: 23

You can pass lists as arguments to a function, just like any other variable:

# Returns the first even number from a list.
def first_even_number(L):
    for x in L:
        if x % 2 == 0:
            return x

# This might look like five arguments, but is actually just one argument in a list.
first_even_number([3, 5, 4, 6, 8])
4

Nested Lists#

One of the most important type of object we can store in a list is other lists. In the following example, we create a list containing 2 lists, each of length 2. We might use this to represent a \(2\times 2\) matrix, where each inner list represents a row.

mat = [[1, 0], [-0.3, 4]]

In order to access the elements of the inner lists, simply use two sets of square brackets like so:

# first row, second entry
mat[0][1]
0

In practice, if you are working with matrices of numbers you will almost always want to use an array from numpy instead of a list-of-lists; these are detailed in another Notebook.

Aside: we can even put a list inside itself! This is almost always a recipe for trouble.

L = [1, 2, 3]
L.append(L)
L
[1, 2, 3, [...]]

Tuples#

Another way of representing a sequence of objects is as a tuple. These behave very similarly to lists, with the major difference that you cannot alter the contents of a tuple once it is created (it is immutable). This might seem inconvenient, but it is often very useful. The guarantee that a tuple will not change can add some “safety” to your code and make it easier to reason with. To create a tuple, use round brackets ( ) instead of square brackets:

tup = (1, 2, 3)

# access the elements just like a list
tup[1]
2

If you need to create a tuple with a single element (say the number \(1\)), you cannot just write (1) as you would write [1] to create a list. This is because Python will interpret (1) as a bracketed expression which evaluates to \(1\), rather than a tuple containing \(1\). Instead, write (1,):

tup = (1,)

len(tup)
1

Since tuples are immutable, you cannot add or remove elements from them:

tup.append(1)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [20], in <cell line: 1>()
----> 1 tup.append(1)

AttributeError: 'tuple' object has no attribute 'append'

You can convert between tuples and lists using the tuple and list functions:

L = [1, 2, 3]

tuple(L)
(1, 2, 3)
tup = ("a", "b", "c")

list(tup)
['a', 'b', 'c']