$$ \newcommand{\tp}{\thinspace .} $$

This chapter is taken from the book A Primer on Scientific Programming with Python by H. P. Langtangen, 5th edition, Springer, 2016.

Lists

Up to now a variable has typically contained a single number. Sometimes numbers are naturally grouped together. For example, all Celsius degrees in the first column of our table from the section While loops could be conveniently stored together as a group. A Python list can be used to represent such a group of numbers in a program. With a variable that refers to the list, we can work with the whole group at once, but we can also access individual elements of the group. Figure 1 illustrates the difference between an int object and a list object. In general, a list may contain a sequence of arbitrary objects in a given order. Python has great functionality for examining and manipulating such sequences of objects, which will be demonstrated below.


Figure 1: Illustration of two variables: var1 refers to an int object with value 21, created by the statement var1 = 21, and var2 refers to a list object with value [20, 21, 29, 4.0], i.e., three int objects and one float object, created by the statement var2 = [20, 21, 29, 4.0].

Basic list operations

To create a list with the numbers from the first column in our table, we just put all the numbers inside square brackets and separate the numbers by commas:

C = [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
The variable C now refers to a list object holding 13 list elements. All list elements are in this case int objects.

Every element in a list is associated with an index, which reflects the position of the element in the list. The first element has index 0, the second index 1, and so on. Associated with the C list above we have 13 indices, starting with 0 and ending with 12. To access the element with index 3, i.e., the fourth element in the list, we can write C[3]. As we see from the list, C[3] refers to an int object with the value \( -5 \).

Elements in lists can be deleted, and new elements can be inserted anywhere. The functionality for doing this is built into the list object and accessed by a dot notation. Two examples are C.append(v), which appends a new element v to the end of the list, and C.insert(i,v), which inserts a new element v in position number i in the list. The number of elements in a list is given by len(C). Let us exemplify some list operations in an interactive session to see the effect of the operations:

>>> C = [-10, -5, 0, 5, 10, 15, 20, 25, 30]     # create list
>>> C.append(35)              # add new element 35 at the end
>>> C                         # view list C
[-10, -5, 0, 5, 10, 15, 20, 25, 30, 35]
Two lists can be added:

>>> C = C + [40, 45]          # extend C at the end
>>> C
[-10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
What adding two lists means is up to the list object to define, and not surprisingly, addition of two lists is defined as appending the second list to the first. The result of C + [40,45] is a new list object, which we then assign to C such that this name refers to this new list. In fact, every object in Python and everything you can do with it is defined by programs made by humans. With the techniques of class programming you can create your own objects and define (if desired) what it means to add such objects. All this gives enormous power in the hands of programmers. As one example, you can define your own list object if you are not satisfied with the functionality of Python's own lists.

New elements can be inserted anywhere in the list (and not only at the end as we did with C.append):

>>> C.insert(0, -15)          # insert new element -15 as index 0
>>> C
[-15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
With del C[i] we can remove an element with index i from the list C. Observe that this changes the list, so C[i] refers to another (the next) element after the removal:

>>> del C[2]                  # delete 3rd element
>>> C
[-15, -10, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
>>> del C[2]                  # delete what is now 3rd element
>>> C
[-15, -10, 5, 10, 15, 20, 25, 30, 35, 40, 45]
>>> len(C)                    # length of list
11
The command C.index(10) returns the index corresponding to the first element with value 10 (this is the 4th element in our sample list, with index 3):

>>> C.index(10)               # find index for an element (10)
3
To just test if an object with the value 10 is an element in the list, one can write the boolean expression 10 in C:

>>> 10 in C                   # is 10 an element in C?
True
Python allows negative indices, which leads to indexing from the right. As demonstrated below, C[-1] gives the last element of the list C. C[-2] is the element before C[-1], and so forth.

>>> C[-1]                     # view the last list element
45
>>> C[-2]                     # view the next last list element
40

Building long lists by writing down all the elements separated by commas is a tedious process that can easily be automated by a loop, using ideas from the section Loop implementation of a sum. Say we want to build a list of degrees from -50 to 200 in steps of 2.5 degrees. We then start with an empty list and use a while loop to append one element at a time:

C = []
C_value = -50
C_max = 200
while C_value <= C_max:
     C.append(C_value)
     C_value += 2.5
In the next sections, we shall see how we can express these six lines of code with just one single statement.

There is a compact syntax for creating variables that refer to the various list elements. Simply list a sequence of variables on the left-hand side of an assignment to a list:

>>> somelist = ['book.tex', 'book.log', 'book.pdf']
>>> texfile, logfile, pdf = somelist
>>> texfile
'book.tex'
>>> logfile
'book.log'
>>> pdf
'book.pdf'
The number of variables on the left-hand side must match the number of elements in the list, otherwise an error occurs.

A final comment regards the syntax: some list operations are reached by a dot notation, as in C.append(e), while other operations requires the list object as an argument to a function, as in len(C). Although C.append for a programmer behaves as a function, it is a function that is reached through a list object, and it is common to say that append is a method in the list object, not a function. There are no strict rules in Python whether functionality regarding an object is reached through a method or a function.

For loops

The nature of for loops

When data are collected in a list, we often want to perform the same operations on each element in the list. We then need to walk through all list elements. Computer languages have a special construct for doing this conveniently, and this construct is in Python and many other languages called a for loop. Let us use a for loop to print out all list elements:

degrees = [0, 10, 20, 40, 100]
for C in degrees:
    print 'list element:', C
print 'The degrees list has', len(degrees), 'elements'
The for C in degrees construct creates a loop over all elements in the list degrees. In each pass of the loop, the variable C refers to an element in the list, starting with degrees[0], proceeding with degrees[1], and so on, before ending with the last element degrees[n-1] (if n denotes the number of elements in the list, len(degrees)).

The for loop specification ends with a colon, and after the colon comes a block of statements that does something useful with the current element. Each statement in the block must be indented, as we explained for while loops. In the example above, the block belonging to the for loop contains only one statement. The final print statement has the same indentation (none in this example) as the for statement and is executed as soon as the loop is terminated.

As already mentioned, understanding all details of a program by following the program flow by hand is often a very good idea. Here, we first define a list degrees containing 5 elements. Then we enter the for loop. In the first pass of the loop, C refers to the first element in the list degrees, i.e., the int object holding the value 0. Inside the loop we then print out the text 'list element:' and the value of C, which is 0. There are no more statements in the loop block, so we proceed with the next pass of the loop. C then refers to the int object 10, the output now prints 10 after the leading text, we proceed with C as the integers 20 and 40, and finally C is 100. After having printed the list element with value 100, we move on to the statement after the indented loop block, which prints out the number of list elements. The total output becomes

list element: 0
list element: 10
list element: 20
list element: 40
list element: 100
The degrees list has 5 elements
Correct indentation of statements is crucial in Python, and we therefore strongly recommend you to work through Exercise 23: Explore problems with inaccurate indentation to learn more about this topic.

Making the table

Our knowledge of lists and for loops over elements in lists puts us in a good position to write a program where we collect all the Celsius degrees to appear in the table in a list Cdegrees, and then use a for loop to compute and write out the corresponding Fahrenheit degrees. The complete program may look like this:

Cdegrees = [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
for C in Cdegrees:
    F = (9.0/5)*C + 32
    print C, F
The print C, F statement just prints the value of C and F with a default format, where each number is separated by one space character (blank). This does not look like a nice table (the output is identical to the one shown in the section A naive solution. Nice formatting is obtained by forcing C and F to be written in fields of fixed width and with a fixed number of decimals. An appropriate printf format is %5d (or %5.0f) for C and %5.1f for F. We may also add a headline to the table. The complete program becomes:

Cdegrees = [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
print '    C    F'
for C in Cdegrees:
    F = (9.0/5)*C + 32
    print '%5d %5.1f' % (C, F)
This code is found in the file c2f_table_list.py and its output becomes

    C    F
  -20  -4.0
  -15   5.0
  -10  14.0
   -5  23.0
    0  32.0
    5  41.0
   10  50.0
   15  59.0
   20  68.0
   25  77.0
   30  86.0
   35  95.0
   40 104.0