Lists and Tuples
In this posts we intend to introduce the use of lists and tuples for those who are new to programming or are migrating from some other language, as well as those who have been in Python for a while and want to expand their knowledge and improve their code. As a first approach, it could be said that lists and tuples are what we in other languages call vectors or arrays. However, they have several differences that we'll learn through this tutorial.
A list is not the same as a tuple. Both are an ordered set of values. Values can be any Python object: numbers, strings, functions, classes, instances, etc., and even other lists and tuples. The difference is that lists have a series of additional functions that allow an extensive handling of the values they contain. On the contrary, the content of a tuple cannot be changed once created. Thus we can state that lists are dynamic or mutable, while tuples are static or immutable. Let's start with lists.
Creating a List¶
There are two ways to create a list: either by using square brackets or by calling the built-in list()
function. There is rarely a reason to use the later, but it is worth knowing that it exists.
Two square brackets create an empty list with no values. These can be specified during creation by entering them inside the square brackets and separated by commas.
Each of the values is generally called an element. Note that it is not necessary to indicate the number of elements that the object has or will have. In this case, the list has four numeric elements. However, both lists and tuples can contain elements of different types, for example:
The third element of this b
list is a tuple, as we shall see now.
Creating a Tuple¶
As with lists, there are two ways to create a tuple:
Since tuples are immutable, you must specify its elements during creation:
If you want to create a tuple with a single element, you must add a comma before closing the last parentheses, since parentheses are also used to group expressions:
Reading and Writing Elements¶
You can access the different elements of a list or tuple by indicating the index (starting from 0) between square brackets.
If the index is out of range, you will get an exception.
|
>>> a[3]
|
|
Traceback (most recent call last):
|
|
File "<stdin>", line 1, in <module>
|
|
IndexError: list index out of range
|
This happens because a
contains only three elements identified by the 0
, 1
, and 2
indexes.
Once a list is created, you can add as many values as you want.
The append()
method will add the specified element to the end of the list.
You can also alter existing elements by combining the access method with the assignment method:
Notice how the values in indexes 2
and 0
have been modified.
You might insert an element wherever you want, using the insert()
method. For example:
The insert()
method takes the place or index as the first argument, and the element as the second one. Other examples:
Removing Elements¶
The remove()
method of a list will remove the first element that matches the given value as an argument.
If the element is not found in the list, ValueError
is raised.
|
>>> a.remove("Fish")
|
|
Traceback (most recent call last):
|
|
File "<stdin>", line 1, in <module>
|
|
ValueError: list.remove(x): x not in list
|
To remove the element at a given position, use the del
reserved keyword followed by list[index]
.
|
>>> a = ["Apple", "Pear", "Banana", "Orange"]
|
|
>>> del a[1]
|
|
>>> a
|
|
['Apple', 'Banana', 'Orange']
|
|
>>> del a[2]
|
|
>>> a
|
|
['Apple', 'Banana']
|
And to remove all elements:
Later we will see how the the :
character works and you will understand why this method is used. Not to be confused with del a
, which will remove the reference to the list.
Counting Elements¶
The len()
built-in function allows you to count the number of elements that a list or tuple contains.
The len()
function doesn't actually count the amount of elements every time it is called, it just reads an attribute stored in the list or tuple object. So feel free to use len()
inside loops without caching.
Since the tuple has three elements, the last one will be found at len(a) - 1
(because indexes start from 0
).
Casting¶
You can convert lists to tuples and vice-versa using the built-in functions we saw above: list()
and tuple()
. For example:
Slicing¶
To slice a list or a tuple means to extract a little portion of elements from within it.
|
>>> a = ["C", "C++", "Python", "Perl", "PHP", "Pascal"]
|
|
>>> b = a[2:5]
|
|
>>> b
|
|
['Python', 'Perl', 'PHP']
|
As you can see, a list or tuple can take a starting index and an ending index to order to take a slice from the sequence. The slicing expression creates a new a list or tuple and copies the elements within the range specified from the source sequence. So if you make changes to b
, nothing happens in a
, and vice-versa.
In this case, a[2:5]
indicates to take the values at indexes 2, 3, and 4 (note that 5 is not included). The syntax is object[start:end]
. If start
is not specified, it defaults to 0. If end
is not specified, it defaults to the amount of elements contained in the object, i. e. len(object)
.
Also, negative values can be used as indexes to start counting from the end. For example, to get the last item in the list:
Which is equivalent to:
And to get all elements but the last one:
Or removing the last three:
A third number called step
might be added when slicing, which indicates the "space" between the elements taken from the original list or tuple. For example:
|
>>> a = list(range(20))
|
|
>>> a
|
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
|
|
>>> a[5:15:2]
|
|
[5, 7, 9, 11, 13]
|
In this case, in a list of 20 elements (from 0 to 19), elements of indexes from 5 to 14 are taken (since the last number is exclusive) but instead of returning all of them, they are returned every two (because the step
is 2
). Other examples:
So the full slicing syntax is object[start:end:step]
, where step
is the amount by which the index increases while taking elements from the sequence.
Finally, slicing can also be used to modify values as a whole. For example:
|
>>> a = ["C", "C++", "Python", "Perl", "PHP"]
|
|
>>> a[1:4] = "C++11", "Python 2.7", "Perl 5"
|
|
>>> a
|
|
['C', 'C++11', 'Python 2.7', 'Perl 5', 'PHP']
|
This does not apply to tuples since they do not allow assignment of new values.
Membership and Iteration¶
The clearest way to determine whether a value is inside a list or a tuple is to use the in
reserved keyword.
|
>>> a = (1, 2, 3, 4)
|
|
>>> 3 in a
|
|
True
|
|
>>> 5 in a
|
|
False
|
|
>>> "CPython" in ["PyPy", "Jython", "IronPython"]
|
|
False
|
And it might also be used along with the not
keyword:
There are several methods to iterate or traverse the elements of a tuple or list. In other languages, a numeric variable is usually created that stores the value of the current index. For example, in C:
This translates to the Python language as:
And produces the following output:
1 2 3 4 5
However, there is a nicer, cleaner method, in which the language assigns the proper value to an object during iteration.
The indented part of the code (the one that starts with 4 spaces) will be executed len(a)
times, that is, 5 times. In the first iteration, a
will be 1
; in the second, 2
; in the third, 3
; and so on. Let's look at another example:
Which prints:
Hello Python Assets 2022 True
Sometimes it might be necessary to keep the index of each element. The enumerate()
built-in function can help us with this. To understand how it works, let's look at the following example.
This creates an enumerate
object, which converted to a list is a set of tuples containing (index, value)
for each element. In addition, the number from which the count needs to start (0 by default) might be indicated.
When using it in a loop, there is no need to cast it to a list.
|
>>> for index, item in enumerate(a, 1):
|
|
... print(f"Item {index}: {item}")
|
|
...
|
|
Item 1: Hello.
|
|
Item 2: Python.
|
|
Item 3: Assets.
|
|
Item 4: 2022.
|
|
Item 5: True.
|
This piece of code is equivalent to the following in other languages:
Unpacking¶
To unpack a sequence in Python is to put the values within it into a set of objects.
This expression is equivalent to:
As long as seq
contains three elements. If it has more or less, an exception (ValueError
) will be raised. Some examples:
More methods and utilities¶
Below is an explanation directly put into practice, because the methods have very descriptive names.
|
# Add the elements to the end of the list.
|
|
>>> a = [1, 2, 3, 4]
|
|
>>> a.extend([5, 6, 7, 8, 9])
|
|
>>> a
|
|
[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
# Remove an item by index and get the removed value.
|
|
>>> a = ["CPython", "PyPy", "Jython"]
|
|
>>> removed = a.pop(1)
|
|
>>> removed
|
|
'PyPy'
|
|
>>> to
|
|
['CPython', 'Jython']
|
|
# How many times an item appears in the list?
|
|
>>> a = ["Dog", "Cat", "Dog", "Horse", "Dog", "Cat"]
|
|
>>> a.count("Dog")
|
|
3
|
|
>>> a.count("Horse")
|
|
1
|
|
>>> a.count("Cat")
|
|
2
|
|
# Sort elements from smallest to greatest.
|
|
>>> a = [4, 7, 5, 6, 2, 1, 3]
|
|
>>> a.sort()
|
|
>>> a
|
|
[1, 2, 3, 4, 5, 6, 7]
|
|
# Can be used in conjunction with sort() to sort from greatest to smallest.
|
|
>>> a = [4, 7, 5, 6, 2, 1, 3]
|
|
>>> a.sort()
|
|
>>> a.reverse()
|
|
>>> a
|
|
[7, 6, 5, 4, 3, 2, 1]
|
The zip()
built-in function is very useful when we need to traverse two or more sequences at the same time. For example:
Another example:
Sets¶
Finally, a set
is a collection of unique, unordered values, which means its elements cannot be repeated. Neither can elements be accessed through an index, such as lists or tuples, since it is an unordered collection of values.
A set is created putting its elements between braces (like a dictionary, but no colons):
It might also be created from an iterable object (such as a list or tuple). For example:
If the iterable object has repeated values, they will be removed.
Taking this into account, an interesting method to remove repeated values from a list or tuple is:
Examples:
|
>>> a = (1, 1, 2, 2, 3, 3)
|
|
>>> tuple(set(a))
|
|
(1, 2, 3)
|
|
>>> b = ["CPython", "IronPython", "Jython", "Jython", "CPython"]
|
|
>>> list(set(b))
|
|
['IronPython', 'Jython', 'CPython']
|
Other set methods: