This lesson is being piloted (Beta version)

Lists and indexing

Overview

Teaching: 35 min
Exercises: 25 min
Questions
  • How can I store multiple values?

Objectives
  • Explain why programs need collections of values.

  • Write programs that create flat lists, index them, slice them, and modify them through assignment and method calls.

Lists are collections of data

We have already encountered some simple Python types like integers, strings and booleans. Now we will see how we can group multiple values together in a collection – like a list of numbers or a list of names. Collections in Python are containers that are used to store collections of data, and include lists, tuples and dictionaries, which we will cover in future lessons.

weights = [173, 175, 277, 275, 176]
print('weights:', weights)
print('length:', len(weights))
weights: [173, 175, 277, 275, 176]
length: 5

Use an item’s index to fetch it from a list

print('zeroth item of weights:', weights[0])
print('fourth item of weights:', weights[4])
zeroth item of weights: 173
fourth item of weights: 176

Reverse indexing, from right to left, also works

weights[-1]
weights[-3]

Using reverse indexing.

How would you extract the letter l from letters using reverse indexing?

letters = list('letters')
letters[____]

Solution

letters[-7]

List values can be replaced in place

weights[0] = 265
print('weights is now:', weights)
weights is now: [265, 175, 277, 275, 176]

Basic operations with lists

Similar to strings, lists respond to the + and * operators. These operators also mean concatenation and repetition, respectively, except that the result is a new list, not a string.

What do the following commands print?

concatenate = [1, 2, 3] + [4, 5, 6]
print('concatenate is:', concatenate)
repetition = ['Hi!'] * 4
print('repetition is:', repetition)

Solution

The program prints

concatenate is: [1, 2, 3, 4, 5, 6]
repetition is: ['Hi!', 'Hi!', 'Hi!', 'Hi!']

List methods

primes = [2, 3, 5]
print('primes is initially:', primes)
primes.append(7)
primes.append(9)
print('primes has become:', primes)
primes is initially: [2, 3, 5]
primes has become: [2, 3, 5, 7, 9]

For example:

teen_primes = [11, 13, 17, 19]
middle_aged_primes = [37, 41, 43, 47]
print('primes is currently:', primes)
primes.extend(teen_primes)
print('primes has now become:', primes)
primes.append(middle_aged_primes)
print('primes has finally become:', primes)
primes is currently: [2, 3, 5, 7, 9]
primes has now become: [2, 3, 5, 7, 9, 11, 13, 17, 19]
primes has finally become: [2, 3, 5, 7, 9, 11, 13, 17, 19, [37, 41, 43, 47]]

Note that while extend maintains the “flat” structure of the list, append a list to a list makes the result two-dimensional.

Fill in the blanks

Fill in the blanks list methods so that the program below produces the output shown. Hint: start with an empty list

values = ____
values.____(1)
values.____()
values.____()
print('new values:', values)
new values: [1, 3, 5]

For example:

a = ['spam', 'spam', 'eggs', 'spam']
print(a.count('spam'))
print(a.count('eggs'))
print(a.count('bacon'))
print(a.count(5))
3
1
0
0

Use del to remove items from a list

primes = [2, 3, 5, 7, 9]
print('primes before removing last item:', primes)
del primes[4]
print('primes after removing last item:', primes)
primes before removing last item: [2, 3, 5, 7, 9]
primes after removing last item: [2, 3, 5, 7]

The empty list contains no values

True or False?

What do you think this evaluates to:

type([])
bool([])

Lists may contain values of different types

goals = [1, 'Create lists.', 2, 'Extract items from lists.', 3, 'Modify lists.']

Character strings can be indexed like lists

element = 'carbon'
print('zeroth character:', element[0])
print('third character:', element[3])
zeroth character: c
third character: b

But unlike lists, character strings are immutable

element[0] = 'C'
TypeError: 'str' object does not support item assignment

Indexing beyond the end of the collection is an error

random_chr = ['±', '!', '@', '#', '$', '%']
print("length of random_chr:", len(random_chr))
print("get the 20th element of random_chr:", random_chr[20])
length of random_chr: 6
IndexError: list index out of range

Slicing python lists

Let’s create a normal, everyday list with letters from a to h. Now let’s say that we really want the elements b, c, and d returned in a new list. How do we do that?

letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
letters[1:4]
['b', 'c', 'd']

Slice bounds

One way to remember how slices work is to think of the indices as pointing between elements, with the left edge of the first character numbered 0.


+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
0   1   2   3   4   5   6   7   8
-8  -7  -6  -5  -4  -3  -2  -1

Slice indices have useful defaults

letters[4:] # list elements from position 4 (included) onwards ... counting from 0!
['e', 'f', 'g', 'h']
letters[:5] # list elements from the beginning to position 5 (excluded)
['a', 'b', 'c', 'd', 'e']
print('last item in the list:', letters[-1])
print('last two items in the list:', letters[-2:])
print('everything except the last two items:', letters[:-2])
last item in the list: h
last two items in the list: ['g', 'h']
everything except the last two items: ['a', 'b', 'c', 'd', 'e', 'f']

Fill in the blanks

Fill in the blanks using methods of lists and slicing so that the program below produces the output shown. Hint: start with an empty list

print('first time:', values)
values = values[____]
print('second time:', values)
first time: [1, 3, 5]
second time: [3, 5]

Solution

print('first time:', values)
values = values[1:]
print('second time:', values)

Stepping through a list

What does the following program print?

elements = ['H', 'He', 'Li', 'B', 'O', 'F', 'Mg', 'P', 'Mn', 'Cu']
print(elements[::2])
print(elements[::-1])

Answer the following questions.

  1. If we write a slice as low:high:stride, what does stride do?
  2. What expression would select all of the even-numbered items from a collection?

Solution

The program prints

['H', 'Li', 'O', 'Mg', 'Mn']
['Cu', 'Mn', 'P', 'Mg', 'F', 'O', 'B', 'Li', 'He', 'H']
  1. stride is the step size of the slice
  2. The slice 1::2 selects all even-numbered items from a collection: it starts with element 1 (which is the second element, since indexing starts at 0), goes on until the end (since no end is given), and uses a step size of 2 (i.e., selects every second element).

Using functions and methods on lists and strings

From strings to lists and back

Given this:

print('string to list:', list('tin'))
print('list to string:', ''.join(['g', 'o', 'l', 'd']))
['t', 'i', 'n']
'gold'
  1. Explain in simple terms what list('some string') does.
  2. What does 'hello'.join(['x','y']) generate?

Solution

  1. list('some string') “splits” a string into a list of its characters.
  2. 'xhelloy'

Sort and sorted

What do these two programs print? In simple terms, explain the difference between sorted(letters) and letters.sort().

# Program A
letters = list('gold')
result = sorted(letters)
print('letters is', letters, 'and result is', result)
# Program B
letters = list('gold')
result = letters.sort()
print('letters is', letters, 'and result is', result)

Solution

Program A prints

letters is ['g', 'o', 'l', 'd'] and result is ['d', 'g', 'l', 'o']

Program B prints

letters is ['d', 'g', 'l', 'o'] and result is None

sorted(letters) returns a sorted copy of the list letters (the original list letters remains unchanged), while letters.sort() sorts the list letters in-place and does not return anything.

Another type of collection: Tuples

In Python programming, a tuple is similar to a list: a collection of data elements. The difference between the two is that tuples are immutable, we cannot change the elements of a tuple once it is assigned, whereas a list is mutable, elements can be changed in place. Also, while lists use square brackets [], tuples use parentheses ().

Challenge question

Can you think of any advantages of using tuples over lists? Some of these concepts will become clearer in future chapters.

Solution

  1. If you have data that doesn’t change, implementing it as tuple will guarantee that it remains write-protected.
  2. Tuples are faster than lists. If you’re defining a constant set of values and all you’re ever going to do with it is iterate through it, use a tuple instead of a list.
  3. One good thing about tuples is that they use less memory. Lists use more memory.
  4. Tuple are better for heterogeneous (different) datatypes and list for homogeneous (similar) datatypes.

Creating a Tuple

What would be the ouput of the following commands?

tupl1 = ('d','a','t','a')
tupl2 = tupl1 + tuple('is') + (tuple('fun') * 3)
print(tupl2)

Solution

('d', 'a', 't', 'a', 'i', 's', 'f', 'u', 'n', 'f', 'u', 'n', 'f', 'u', 'n')

Another advantage of tuples is that they contain immutable elements that can be used as keys for a dictionary. With list, this is not possible. We will learn more about keys and dictionaries in a future chapter.

Key Points

  • A list stores many values in a single structure.

  • Use an item’s index to fetch it from a list.

  • Lists are mutable: list values can be replaced by assigning to them.

  • Appending items to a list lengthens it.

  • Use del to remove items from a list entirely.

  • The empty list contains no values.

  • Lists may contain values of different types.

  • Character strings can be indexed like lists.

  • Python uses 0-based indexing. The first index is zero, the second index is one, and so forth

  • Indexing beyond the end of the collection is an error.

  • Tuples are another type of collection, but unlike lists, tuples are immutable.