Lists, Loops and range

We can store collections of data, using Python's type list.

For example, here are the average gross annual earnings for anesthesiologists, ophthalmologists, cardiologists, pediatricians, and family doctors, respectively (from https://www.cma.ca/Assets/assets-library/document/en/advocacy/Anesthesiology-e.pdf and similar sources on cma.ca).

  • 361,681
  • 740,741
  • 396,105
  • 284,600
  • 249,154

The general form of a list is:

[expression1, expression2, ..., expressionN]

We can store the data in Python as follows:

In [1]:
gross_earnings = [361681, 740741, 396105,  284600, 249154]

We enclose the data in square brackets, and items of the list (also called elements) are separated by commas. We access an element using its index -- the order of the element in the list, starting from 0.

In [2]:
gross_earnings[0]
Out[2]:
361681
In [3]:
gross_earnings[1]
Out[3]:
740741
In [4]:
gross_earnings[4]
Out[4]:
249154

Note that, since there are 5 elements in the list and we start counting from 0, we only have indices 0, 1, 2, 3, and 4. The following produces an error:

In [5]:
gross_earnings[5]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-5-57b472f13599> in <module>()
----> 1 gross_earnings[5]

IndexError: list index out of range

The expression gross_earnings[2] gives a float value, so you can use the expression gross_earnings[2] anywhere that you can use a float. For example:

In [6]:
0.6 * (gross_earnings[2] + 500)
Out[6]:
237963.0

You can access an element of a list, by using a variable to represent the index:

In [7]:
i = 2
gross_earnings[i]
Out[7]:
396105

The variable name i is commonly used when the variable represents an index.

Functions and operations on lists

As we did for objects of type str, we can obtain the length of a list using Python's function len.

In [8]:
len(gross_earnings)
Out[8]:
5

The function call produced 5, because there are five elements in the list that gross_earnings refers to.

Since the list has 5 elements, the valid indexes into the list are 0, 1, 2, 3, and 4. In general, the last index is equal to the length of the list minus one:

In [9]:
gross_earnings[len(gross_earnings) - 1]
Out[9]:
249154

Here is another example of using len to calculate the last index and to access the last element in the list:

In [10]:
L = [4, 5, 6]
print("Length of L:", len(L))
print("The index of the last element of L:", len(L)-1)
print("The last element of L:", L[len(L)-1])
Length of L: 3
The index of the last element of L: 2
The last element of L: 6

Alternatively, we can use negative indexes to access the elements of a list, with index -1 corresponding with the right-most element:

In [11]:
print(L[-1])  # same as L[len(L)-1]
print(L[-2])  # same as L[len(L)-2]
6
5

There are several other functions that can take lists as arguments, including min, max, and sum:

In [12]:
values = [5.4, 6, 3.2, 8.1, 11]
print(min(values))
print(max(values))
print(sum(values))
3.2
11
33.7

We can also use the operator in to check whether an object is an item in a list:

In [18]:
heart_rates = [78, 85, 90, 100, 97]
85 in heart_rates
Out[18]:
True
In [19]:
95 in heart_rates
Out[19]:
False

for loop over range

Python has a built-in function named range that produces a sequence of numbers. Here is a fragment of the documentation for range:

range(start, stop[, step]) -> range object
 |  
 |  Return an object that produces a sequence of integers from start (inclusive)
 |  to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.
 |  start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.
 |  These are exactly the valid indices for a list of 4 elements.
 |  When step is given, it specifies the increment (or decrement).

We can use a for loop to iterate over the sequence produced by range. The first number is the sequence is by default 0 and the sequence continues up to but not including the argument to range:

In [23]:
for num in range(10):
    print(num)
0
1
2
3
4
5
6
7
8
9

If we want to start at 1 and go up 11, we can pass two arguments:

In [25]:
for num in range(1, 11):
    print(num)
1
2
3
4
5
6
7
8
9
10

We can also specify the step size, so let's use that to print even numbers from 10 to 20 inclusive:

In [28]:
for value in range(10, 21, 2):
    print(value)
10
12
14
16
18
20

Practice Exercise: range

Use range and a for loop to print every 4th number from 0 to 200, inclusive

for loop over list

Let's print out each item from gross_earnings:

In [13]:
print(gross_earnings[0])
print(gross_earnings[1])
print(gross_earnings[2])
print(gross_earnings[3])
print(gross_earnings[4])
361681
740741
396105
284600
249154

The code above works, but what if there are 100 or even 100,000 items in gross_earnings? We'd have to call print once for each of them!

The only thing that varies in each line of code above is the index. We can use a variable to represent the index and change the value of the variable so that it to refers to the values 0, 1, 2, 3, and 4. Here is one approach for solving this, using range and a for loop:

In [14]:
for i in range(5):
    print(gross_earnings[i])
361681
740741
396105
284600
249154

We can make the code even more general and replace 5 with the length of the list, so that this code will work regardless of the number of items in gross_earnings:

In [15]:
for i in range(len(gross_earnings)):
    print(gross_earnings[i])
361681
740741
396105
284600
249154

As an alternative, we can use a for loop to iterate over the items in gross_earnings:

In [16]:
for salary in gross_earnings:
    print(salary)
361681
740741
396105
284600
249154

In the code above, variable salary first refers to gross_earnings[0], then gross_earnings[1], and so on, until the end of the list is reached.

Worked example: Printing particular elements

Let's write code to print the items of gross_earnings that are less than 300,000.

Here is an English description of our approach to this problem: for each item in gross_earnings, check whether it is less than 300000 and if so, print it. Now, here is the code:

In [31]:
gross_earnings = [361681, 740741, 396105,  284600, 249154]
for i in range(len(gross_earnings)):
    if gross_earnings[i] < 300000:
        print(gross_earnings[i])
    
284600
249154

Let's trace the code above using the Python Visualizer.

An alternative approach is to iterate over the list directly:

In [32]:
for salary in gross_earnings:
    if salary < 300000:
        print(salary)
284600
249154

We can also trace the code above using the Python Visualizer to see how it differs from the previous version.

Computing the sum of a list

Suppose we want to compute the sum of all the values in a list. We can use the numeric accumulator pattern that we used with strings.

Here's the idea: we'll set up a variable total that initially refers to 0, and we'll keep adding adding values to it.

Initially, total will refer to 0.

Then we'll add gross_earnings[0] to total.

Next, we'll add gross_earnings[1] to total.

and so on ...

Finally, we'll add gross_earnings[len(gross_earnings)-1] to total.

Here is how to express this in Python:

In [33]:
gross_earnings = [361681, 740741, 396105,  284600, 249154]
total = 0    
for i in range(len(gross_earnings)):
    total = total + gross_earnings[i]
    print("At iteration", i, "total = ", total)

print("Final total:", total)   
At iteration 0 total =  361681
At iteration 1 total =  1102422
At iteration 2 total =  1498527
At iteration 3 total =  1783127
At iteration 4 total =  2032281
Final total: 2032281

It isn't necessary to print out the intermediate values of total, of course. We just did that for illustration purposes.

Practice Exercise: Iteration and Accumulation

Once we know the sum of a list, computing the average is straight forward: all we need to do is divide the sum by the number of elements.

First, consider how you can get the number of items in a list, using one of Python's built-in functions.

Now, compute the average of the items in gross_earnings:

In [1]:
gross_earnings = [361681, 740741, 396105,  284600, 249154]

Check your answer: 406456.2

Practice Exercise : Conditional + Loops

Compute the average of gross_earnings, but exclude any earnings that are outside the range from 250000 (inclusive) to 400000 (exclusive).

Check your answer: 347462.0

Practice Exercise: list of str, conditionals, and loops

Consider a list of strings that are represent handedness of subjects in a study and looks something like this:

hands = ["left", "right", "right", "right", "left", "mixed", "right", ...]

The only elements in the list are the strings "right", "left", or "mixed".

Write a program that will work on any such list and print the percentage of subjects from each category of handedness. For example, if you were to run it on the list ["right", "left", "right", "right"], it should print the output: Right-handed: 75 % Left-handed: 25 % Mixed-handed: 0 %

Don’t worry about formatting the numbers. You might see 75.00000 as your result and that’s fine for now. Name your program handed.py.