Lists and Tuples


In this section we will try to go in more depth about lists and tuples in Python. We will show some classic use scenarios and then briefly introduce all functions operating on lists.

Constructors

Earlier we showed how to create lists and tuples using braces or parenthesis, but Python also allows us to create lists and tuples using the list() and tuple() constructors. Here are some useful examples:

1
2
3
4
5
6
7
8
9
10
[] #empty list
list() #also an empty list constructor
 
# Here's an easy way to make a copy of a list
a = [1,2,3,4]
b = list(a) #make a copy of list a
 
# We can use the same technique to convert a tuple to a list or vice versa
a = (1,2,3,4)
list(a) # returns [1, 2, 3, 4]

Size of a List or Tuple

Finding the size of a list or tuple is done with the built-in function len():

1
2
len([1,2,3,4,5])    # returns 5
len(('a', 1, None)) # returns 3

Accessing and Slicing

Accessing a single element in a list or tuple is done using the subscript operator [].

1
2
fruits = ['apple', 'peach', 'mango', 'pear', 'banana']
fruits[1] # returns 'peach'

Accessing an element past the end of the list raises an IndexError:

1
fruits[10]

Output:

IndexError: list index out of range

However, negative indexes are not invalid. They simply count from the end of the list.

1
2
3
fruits[-1]  # returns 'banana'
fruits[-3]  # returns 'mango'
fruits[-10] # IndexError: list index out of range

Several consecutive elements can be extracted from a list with an operation called slicing in Python. We again use [], but we specify a starting and ending index separated by a colon:

1
fruits[1:4] # returns ['peach', 'mango', 'pear']

Negative indexes work with slicing as well.

1
fruits[-4:-1] # returns ['peach', 'mango', 'pear']

Optionally, we can also specify a step size by adding a third number separated with another colon:

1
fruits[1:4:2] # returns ['peach', 'pear']

Once again, a negative step size is valid and simply counts in the other direction (right-to-left):

1
fruits[-1:-4:-1] # returns ['pear', 'mango', 'peach']

Any or all of the three numbers defining a slice may be omitted. When the start index is omitted a 0 is implied and similarly when the end index is omitted, the last index is implied.

1
2
3
4
fruits[:3] #all elements up to the 3rd
=> ['apple', 'peach', 'mango']
fruits[::2] #every other element from start to end
=> ['apple', 'mango', 'banana']

When slicing an array we do not get an IndexError when we try to access past the end of the list. Instead slicing past the end simply returns all elements to the end.

1
2
fruits[1:10]
=> ['peach', 'mango', 'pear', 'banana']

All examples shown above apply to tuples as well.

Concatenation

Similarly to strings, lists and tuples may be concatenated. This is done using the plus operator and the result is a new list or a new tuple depending on the operand types.

1
2
3
4
5
6
[1,2,3] + [4,5]
=> [1, 2, 3, 4, 5]
[1,2,3,4] + (1,2,3,4) #cannot concat different types
=> TypeError: can only concatenate list (not "tuple") to list
(1,2,3,4) + (1,2,3,4)
=> (1, 2, 3, 4, 1, 2, 3, 4)

The operator * may be used as a shorthand to indicate multiple concatenation of a list or tuple with itself.

1
2
3
4
3 * [1,2,3]
=> [1, 2, 3, 1, 2, 3, 1, 2, 3]
('apple', 2) * 2
=> ('apple', 2, 'apple', 2)

Assigning to Elements and Adding New Elements

Here is where we can observe a difference between tuples and lists. Unlike the previous section, the examples here only apply to lists. Assigning to elements and adding new elements implies changing the object and since tuples are immutable these operations are invalid for tuple objects.

Assigning to single elements is simply done by using the subscript operator to access the needed element and then assigning into it using =. Also, remember that lists may contain elements of different types so assigning an integer value over a string is allowed.

1
2
3
fruits = ['apple', 'peach', 'mango', 'pear', 'banana']
fruits[0] = 'kiwi' #change the first element to kiwi
fruits[-1] = 5 #change the last element to the integer 5

If we try to assign into an element of type tuple we get a TypeError:

1
2
3
tuple_fruits = ('apple', 'peach', 'mango', 'pear', 'banana')
tuple_fruits[1] = 'kiwi'
=> TypeError: 'tuple' object does not support item assignment

Assigning into an element past the end of the list is an invalid operations and we again get an IndexError as when we were trying to access past the end

1
2
>>> fruits[10] = 'tomato'
=> IndexError: list assignment index out of range

It is also possible to use a slice on the left-hand side of the assignment operator in which case the whole slice is replaced.

1
2
3
fruits[2:4] = [1,2]
fruits
=> ['apple', 'peach', 1, 2, 'banana']

Using this notation we can even extend, shrink and even completely clear the list:

1
2
3
4
5
6
7
8
9
fruits[2:4] = [1,2,3,4]
fruits
=> ['apple', 'peach', 1, 2, 3, 4, 'banana']
fruits[2:4] = []
fruits
=> ['apple', 'peach', 3, 4, 'banana']
fruits[:] = []
fruits
=> []

Unpacking; Swapping Two Variables

We’ve already seen that a list (or tuple) literal can exist on the right side of an assignment, but interestingly enough Python allows a list or tuple literal on the left side of an assignment as well.

A list (or tuple) on the left side of an assignment must contain only variables (since it is not possible to assign to a literal). The practice of using a list of variables on the left side of an assignment operator is known as unpacking and has some interesting applications.

Here is how to assign two values simultaneously using unpacking:

1
2
(foo, bar) = ("foo", "bar")
foo, bar = "foo", "bar" #we can omit the parenthesis

We can use the same technique to swap the values of two variables:

1
foo, bar = bar, foo #isn't this awesome?

This is probably the cleanest way to swap two variables but beware because it is by no means the fastest. On the other hand if you are using a scripting language you probably should not worry about minor speed optimizations as this one.

Using Lists as Stacks

Python does not have a built-in stack primitive but the built-in list has more than enough power to rectify that.

1
2
3
4
stack = [1,2,3]
stack.append(4) #use append to add elements to the top of the stack
stack.pop() #use pop to pop off the top element
=> 4

Using Lists as Queues

Lists can also be utilized as queues almost the same way:

1
2
3
4
queue = ["foo", "bar"]
queue.append("baz") #use append to add elements to the end of the queue
queue.pop(0) #pop the 0th element of the list to get the 1st element of the queue
=> "foo"

List Methods

A complete list with examples of all list (and tuple) methods can be found in the [list methods][python/list-methods] chapter.