5
By the end of this chapter, you will be able to:
This lesson introduces lists and tuples in Python. We also look at the various list and tuple methods.
A list is a data structure that holds ordered collections of related data. Lists are known as arrays in other programming languages, like Java, C, and C++. Python lists, however, are more flexible and powerful than the traditional arrays of other languages.
An example of this power is that the items in a list do not have to all be of the same type. In other words, we can have a list whose items are strings, integers, or even other lists. The items in a list can be of any of the Python types.
The main properties of Python lists are as follows:
Tuples are used to hold together multiple related objects. They are similar to the lists discussed previously, in that they are also sequence data types, but differ in that they don't have all the functionality afforded by lists. The key difference between lists and tuples is that you cannot change the elements of a tuple once they are set. This property of tuples is called immutability.
As you saw previously, lists can be created in several ways. The simplest of them is to enclose the elements of the list in square brackets [].
Here, you can see several flavors of lists:
# Empty list
[]
# List containing numbers
[2, 4, 6, 8, 10]
# List with mixed types
["one", 2, "three", ["five", 6]]
The first is an initialization of an empty list. The second is a list whose elements are numbers. The last one is an example of a list that contains several types. It has numbers, strings, and sublists inside of it.
The list data type has some built-in methods that can be used with it. These methods are as follows:
Let's take a closer look at what these methods can do.
The list.append(item) method adds a single item to the end of a list. This doesn't return a new list – it only modifies the original. The following is an example of this in use:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
things = ["first"]
things.append("another thing")
things
=> ['first', 'another thing']
The list.extend(iterable) method takes one argument, which should be an iterable data type. It then extends the list by appending all of the items from the iterable to the list. What would happen is we would extend a list with another list:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
things
=> ['first', 'another thing']
others = ["third", "fourth"]
things.extend(others)
things
=> ['first', 'another thing', 'third', 'fourth']
The following code shows what would happen if you passed a string to the extend method:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
things = ["first"]
things.append("another thing")
things
=> ['first', 'another thing']
things.extend("another thing")
things
=> ['first', 'another thing', 'a', 'n', 'o', 't', 'h', 'e', 'r', ' ', 't', 'h', 'i', 'n', 'g']
Note that the extend method used the string as an iterable. This means that it looped through every character in the string (including the space) and appended those characters to the list.
The list.insert(index, item) method (as the name suggests) inserts an item at a given position in a list. The method takes two arguments, index and item. The index is the position in the list before which to insert the item defined in the second argument. Both arguments are required.
To insert an item at the beginning of a list, you would do the following:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
things = ["second"]
things
=> ['second']
things.insert(0, "first")
things
=> ['first', 'second']
The list.remove(item) method removes from the list the first item whose value matches the argument item that's passed in:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
things
=> ['first', 'second']
things.remove("second")
things
=> ['first']
The list.pop([index]) method removes the item at the given index of the list, and returns it. The index is an optional argument, and if it isn't passed in, the method will remove the last item in the list.
The following code shows how it works:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
things
=> ['first', 'second', 'third']
second_item = things.pop(1)
second_item
=> 'second'
things
=> ['first', 'third']
The argument that is passed in is the index of the item that you would like to pop, and not the position. Python list indices start at zero.
As the name suggests, the list.clear() method removes all items from a list. An alternative to this method would be del a[:].
The list.index(item [, start [, end]]) method returns the index of the first item in the list whose value is item.
The parameters start and end are optional, and they indicate the position in the list at which the search for said item should start and end, respectively. Again, the very beginning of the list is index zero. The index at the end of the list is one less than the length of the list.
To search the entire list, simply pass in the item parameter, like this:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
things = ['first', 'second', 'third']
things.index('second')
=> 1
An example of where the start and end parameters are specified is as follows:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
things = ['first', 'second', 'third', 'fourth']
things.index('third', 1, 3)
=> 2
If the specified item is not found in the list, Python raises a ValueError, as follows:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
things = ['first', 'second', 'third', 'fourth']
things.index('fifth')
Traceback (most recent call last):
File "python", line 1, in <module>
ValueError: 'fifth' is not in list
things.index('fourth', 0, 2)
Traceback (most recent call last):
File "python", line 1, in <module>
ValueError: 'fourth' is not in list
The list.count(item) method returns the number of times the given item occurs in the list.
The list.sort(key=None, reverse=False) method sorts the items of the list.
The list.reverse() method reverses the elements of the list.
The list.copy() method returns a shallow copy of a list.
Using your recently gained knowledge of how to use various list methods, work out the following tasks. The aim of this activity is to get acquainted with list methods. Suppose that we have the following list:
Lion, Zebra, Panther, Antelope
We need to change the contents of this list using the various available methods:
Lion, Zebra, Panther, Antelope
Solution for this activity can be found at page 285.
List comprehensions are a feature of Python that give us a clean, concise way to create lists.
A common use case would be when you need to create a list where each element is the result of some operations applied to each member of another sequence or iterable object.
The syntax for a list comprehension is pretty similar to creating a list the traditional way. It consists of square brackets [] containing an expression followed by a for clause, then zero or more if clauses.
Let's go back to the example we looked at previously, where we needed to calculate the squares of numbers. To calculate the squares of all numbers from one to ten using a for loop, we could do the following:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
for num in range(1,11):
print(num**2)
1
4
9
16
25
36
49
64
81
100
The same can be achieved by using list comprehensions, as follows:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
squares = [num**2 for num in range(1, 11)]
squares
=> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
We can also use if statements within list comprehensions. There are really no limitations in what can be done with comprehensions. The following is an example of the preceding code, using an if statement:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
squares = [num**2 for num in range(1, 11) if num%2 == 0]
squares
=> [4, 16, 36, 64, 100]
This particular snippet only adds to the list those squares whose roots are even numbers.
The main advantages of using tuples, rather than lists, are as follows:
A tuple consists of a number of individual values, separated by commas (just like lists). As with lists, a tuple can contain elements of different types. You create a tuple by placing all of the comma-separated values in parentheses, (), like this:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
pets = ('dog', 'cat', 'parrot')
pets
=> ('dog', 'cat', 'parrot')
type(pets)
=> <class 'tuple'>
The parentheses are optional, and you might as well create a tuple using just the comma-separated values, as follows:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
pets = 'dog', 'cat', 'parrot'
pets
=> ('dog', 'cat', 'parrot')
type(pets)
=> <class 'tuple'>
Note that the output version of a tuple will always be enclosed in parentheses, no matter which method you used to create it. This prevents confusion and allows us to better interpret tuples visually.
In this example of a nested tuple, we can see why outputting in this format is important:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
pets = ('dog', 'cat'), 'parrot'
pets
=> (('dog', 'cat'), 'parrot')
Here, we can see that there is a nested tuple, ('dog', 'cat'), inside of the main tuple, and the use of multiple parentheses makes this abundantly clear. This also displays another property of tuples; they can be nested with no limit. Be careful when nesting tuples, though, as several nesting levels may make it difficult to understand and navigate the structure.
What if we wanted to create a tuple with one element? We could just enclose it in parentheses, right? Consider the following code:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
one = ('thing')
one
=> 'thing'
type(one)
=> <class 'str'>
Wrong! As you can see in the preceding example, creating a tuple in this way will only result in a string being created.
You have to recall one very important part of the definition of a tuple: it is a collection of comma-separated values. The comma is very important; therefore, you would have to do something like the following to create a tuple with one element:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
one = 'thing',
one
=> ('thing',)
type(one)
=> <class 'tuple'>
In this exercise, we will create a tuple of our own. We will create a vehicle tuple, add the elements listed as follows, and verify the object type.
The elements are as follows:
>>> vehicle = ('Toyota', 'BMW', 'Benz')
>>> type(vehicle)
<class 'tuple'>
Tuples give us various ways to access their elements. These are as follows:
Similar to lists, we can use the index operator [] to access an element in a tuple by using its index. Tuple indices start at zero, just like those of lists.
In this exercise, you will see how to use indexing to access tuples:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
pets = 'dog', 'cat', 'parrot'
pets[1]
=> 'cat'
pets[3]
Traceback (most recent call last):
File "python", line 1, in <module>
IndexError: tuple index out of range
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
pets = 'dog', 'cat', 'parrot', 'gerbil'
pets[-1]
=> 'gerbil'
pets[-2]
=> 'parrot'
pets[-3]
=> 'cat'
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
pets = 'dog', 'cat', 'parrot'
pets['1']
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: tuple indices must be integers or slices, not str
pets[1.5]
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: tuple indices must be integers or slices, not float
The error message presented here mentions slices, and you might be wondering what slices are. This brings us to the alternative way in which you can access tuple elements: slicing.
While indexing allows you to access an individual element in a tuple, slicing allows you to access a subset, or a slice, of the tuple.
Slicing uses the slicing operator, :, and the general syntax is as follows:
tupleToSlice[Start index (included):Stop index (excluded):Increment]
You have to recall one very important part of the definition of a tuple: it is a collection of comma-separated values. The comma is very important; therefore, you would have to do something like the following to create a tuple with one element:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
one = 'thing',
one
=> ('thing',)
type(one)
=> <class 'tuple'>
In this exercise, we will create a tuple of our own. We will create a vehicle tuple, add the elements listed as follows, and verify the object type.
The elements are as follows:
>>> vehicle = ('Toyota', 'BMW', 'Benz')
>>> type(vehicle)
<class 'tuple'>
Tuples give us various ways to access their elements. These are as follows:
Similar to lists, we can use the index operator [] to access an element in a tuple by using its index. Tuple indices start at zero, just like those of lists.
All of these parameters are optional, and this is how they work:
In this exercise, we will take a look at some practical examples of slicing. Consider a tuple of numbers from one through ten:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
numbers = tuple(range(1,11)])
numbers
=> (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
We will create a list using list comprehensions and cast it to a tuple by using the tuple() method.
To demonstrate tuple slicing, we will to do two things:
In code, that looks something like this:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
numbers = tuple([i for i in range(1,11)])
numbers
=> (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
even = numbers[1::2]
even
=> (2, 4, 6, 8, 10)
For this operation, we set the start index to 1 (the second element of the tuple) and the increment to 2, so that it skips one element every time.
In code, that looks something like this:
Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
numbers = tuple([i for i in range(1,11)])
odd = numbers[::2]
odd
=> (1, 3, 5, 7, 9)
For this operation, we start at index zero (the first element of the tuple) and set the increment to 2, so that it skips one element every time.
Python has the following methods that work with tuples:
>>> pets = ('cat', 'dog', 'horse')
>>> any(pets)
>>> TRUE
This is also the only bound method, as the syntax describes: tuple.count(element). The other methods are unbound:
>>> pets = ('cat', 'dog', 'horse')
>>> pets.count("cat")
>>> 1
>>> pets = ('cat', 'dog', 'horse')
>>> min(pets)
>>> 'cat'
>>> pets = ('cat', 'dog', 'horse')
>>> max(pets)
>>> 'horse'
>>> pets = ('cat', 'dog', 'horse')
>>> len(pets)
>>> 3
>>> pets = ('cat', 'dog', 'horse')
>>> wild = ('lion', 'zebra', 'antelope')
>>> animals = pets + wild
>>> print(animals)
>>> ('cat', 'dog', 'horse', 'lion', 'zebra', 'antelope')
Write a script that uses tuple methods to count the number of elements in a tuple and the number of times a particular element appears in the tuple. Based on these counts, the script will also print a message to the terminal.
The steps are as follows:
pets = ('cat', 'cat', 'cat', 'dog', 'horse')
In this chapter, we expanded our knowledge on Python lists. We have looked at the various methods that are available for lists, and how to use them in practical applications. We have also seen how we can use list comprehensions to make the task of building lists programmatically easier.
Next, we covered Python tuples. We looked at the various methods that are available for tuple operations, and how to use them in practical applications. We have also seen how we can access tuple elements.
In the next chapter, we will cover sets and dictionaries, which are the other data structures that Python offers.