Lists

Python has some different data structures used to store different kinds of data. Each one of them has its own features and uses. In this chapter, we will learn about lists.

If you’re coming from other programming languages, it’s possible you already worked with arrays. Lists are basically the same.

If you didn’t come from other programming languages and Python is your first one, I will explain. Lists are used to store data. Data in a list may be of different types, like integers, strings, decimals, other lists, anything, really.

Creating, modifying and accessing list items

To create a list, we define its items between square brackets ([]), separated by commas. It is also possible to create an empty list, setting only the brackets, with no items inside them. Let’s see some examples.

students = ["José", "João", "Luiz"]
grades = [8.5, 9.2, 6.7]
print(students)
print(grades)
empty_list = []
print(empty_list)

> ['José', 'João', 'Luiz']
> [8.5, 9.2, 6.7]
> []

Note that items doesn’t have to be of the same type. You can mix different types of data inside of a single list.

mixed_list = [12, 15.56, "Ice Cream Store", ["Vanilla", "Chocolate"]]
print(mixed_list)

> [12, 15.56, "Ice Cream Store", ["Vanilla", "Chocolate"]]

The list above, as you saw, has one integer, one float, one string and another list.

To access the items on a list, you use their index, which is the position of the item inside the list. Indexes in Python lists are zero-based, meaning that the first item has index 0 (zero). Let’s see

print(students[0])
print(grades[2])

> José
> 6.7

You can also use negative integers, which makes the counting start from the end of the list:

print(students[-1])
print(students[-3])

> Luiz
> José

Using the same notation, you can change the values in those indexes:

print(grades)
grades[2] = 7.7
print(grades)

> [8.5, 9.2, 6.7]
> [8.5, 9.2, 7.7]

And when we want to add new items in a list? Well, in this case, we can use one of three different ways. First one is append(). This function is called from a list, receives the item to be added. The item is then, added to the end of the list:

print(students) 
students.append('Alfredo')
print(students)

> ['José', 'João', 'Luiz']
> ['José', 'João', 'Luiz', 'Alfredo']

What if we don’t want to append the item in the end? In this case, we have to use insert(). With this function, we first define the index where the new item will be. The subsequent items are adjusted accordingly:

print(students)
students.insert(1, "Daniela")
print(students)

> ['José', 'João', 'Luiz', 'Alfredo']
> ['José', 'Daniela', 'João', 'Luiz', 'Alfredo']

Daniela is now the item on index 1, as defined when calling insert() above.

Finally, we have extend(). This function adds a list to the end of another list

print(students)
new_students = ['Carlos', 'Maria', 'Ana']
students.extend(new_students)
print(students)

> ['José', 'Daniela', 'João', 'Luiz', 'Alfredo']
> ['José', 'Daniela', 'João', 'Luiz', 'Alfredo', 'Carlos', 'Maria', 'Ana']

And it’s also possible to concatenate two lists, using the + sign, as if we were summing the two lists:

students_1 = ['José', 'Daniel', 'João']
students_2 = ['Carlos', 'Augusto', 'Denis']
print(students_1 + students_2)

> ['José', 'Daniel', 'João', 'Maria', 'Ana', 'Carolina']

If you multiply the list by an integer, you will repeat it’s items:

print(grades*2)

> [8.5, 9.2, 7.7, 8.5, 9.2, 7.7]

And if we want to remove? To remove items from a list, we have the remove() and pop() functions. The remove() function erases the item based in its values:

print(students)
students.remove('João')
print(students)

> ['José', 'Daniela', 'João', 'Luiz', 'Alfredo', 'Carlos', 'Maria', 'Ana']
> ['José', 'Daniela', 'Luiz', 'Alfredo', 'Carlos', 'Maria', 'Ana']

If we use remove() and the list has two items with the same value, only the first occurrence will be removed:

students = ['José', 'Denis', 'Daniela', 'Carla', 'Carlos', 'Augusto', 'Denis']
print(students)
students.remove('Denis')
print(students)

> ['José', 'Denis', 'Daniela', 'Carla', 'Carlos', 'Augusto', 'Denis']
> ['José', 'Daniela', 'Carla', 'Carlos', 'Augusto', 'Denis']

Note tha Denis was present twice in the list, but only the first occurrence was removed after using the remove() function, which was the index with index 1.

The pop() function remove an item based in its index. If no index is passed to the function, it will remove the last item on the list. The function also returns the item that was removed:

print(students)
removed_student = students.pop()
print(removed_student)
print(students)
removed_student = students.pop(2)
print(removed_student)
print(students)

> ['José', 'Daniela', 'Luiz', 'Alfredo', 'Carlos', 'Maria', 'Ana']
> Ana
> ['José', 'Daniela', 'Luiz', 'Alfredo', 'Carlos', 'Maria']
> Luiz
> ['José', 'Daniela', 'Alfredo', 'Carlos', 'Maria']

In Python, you can also slice lists, which is the same as extracting parts of the list. To do that, we use the same notation used to retrieve a single item from a list, but we pass the interval, instead of a single index. Let’s see an example:

print(students)
print(students[0:2])
print(students[2:4])
print(students[2:5])

> ['José', 'Daniela', 'Carla', 'Carlos', 'Augusto', 'Denis']
> ['José', 'Daniela']
> ['Carla', 'Carlos']
> ['Carla', 'Carlos', 'Augusto']

Slicing goes from the first element to the last one, excluding the last one. If we omit the first number, it will start on the beginning of the list, and if we omit the second number, it will go until the end of the list.

print(students[:3])
print(students[3:])

> ['José', 'Daniela', 'Carla']
> ['Carlos', 'Augusto', 'Denis']

Like when acessing a single item, it’s also possible to use negative numbers. Counting is also done from the end in this case:

print(students[1:-1])
print(students[2:-2])

['Daniela', 'Carla', 'Carlos', 'Augusto']
['Carla', 'Carlos']

Some useful functions

Here are some useful functions when working with lists.

len()

len(), as with strings, will return the number of items in a list.

print(len(students))

> 6

max() and min()

As funções max() e min(), as it’s probably possible to infer by their names, return the maximum and the minimum value in a list:

print(max(grades))
print(min(grades))

> 9.2
> 7.7

copy()

copy() is the function used to create a copy of a list. If we create a new list using only the assignment sign (=) seems intuitive, but it doesn’t work. This is will only create a new reference to the original list. Let’s see what are the effects of this:

students = ["José", "João", "Luiz", "Carlos", "Afonso"]
backup_students = students
print(backup_students)
students.clear()
print(students)
print(backup_students)

> ['José', 'João', 'Luiz', 'Carlos', 'Afonso']
> []
> []

Note how the backup_students list had the same itens as students, but got empty after we used the clear() function to remove all the items from the students list. What happened is, when we do backup_students in Python, we simply create a reference, without copying it. When we clear the original list, we have students as an empty list, and since backup_students is only a reference, it will also show the empty list when we print it.

Let’s now create a proper copy, using the copy() function (and let’s recreate the students list, which got empty after our last example):

students = ['José', 'Daniela', 'Carla', 'Carlos', 'Augusto', 'Denis']
backup_students = students.copy()
print(backup_students)                                  
students.clear()                                        
print(backup_students)
print(students)

> ['José', 'Daniela', 'Carla', 'Carlos', 'Augusto', 'Denis']
> ['José', 'Daniela', 'Carla', 'Carlos', 'Augusto', 'Denis']
> []

Now, even if we clear the first list, the second one, which is a copy, will remain with its items.

Now, let’s just recreate students so we can use it in the next examples.

students = ['José', 'Daniela', 'Carla', 'Carlos', 'Augusto', 'Denis']

count()

The count() function will return the number of times a certain item occurs in a list. We only have to pass to the function the element we want to count. Let’s add some repeated names to the students list and check how count() works:

students.extend(['Daniela', 'Felipe', 'Carla', 'Daniela'])
print(students.count('Daniela'))

> 3

sort() and sorted()

sort(), as the name implies, sorts a list. It will not return any value, sorting the list in place, permanently.

students.sort()
print(students)

> ['Augusto', 'Carla', 'Carla', 'Carlos', 'Daniela', 'Daniela', 'Daniela', 'Denis', 'Felipe', 'José']

In case you need the items in its original order but want to print a sorted version of the list, you have two options. You can create a copy of the list, using copy(), or you can use the sorted() function. This function receives a list as a parameter and returns the sorted list. In this case, if you want to keep the sorted version of the list, you will have to store it in a variable:

students = ['José', 'Daniela', 'Carla', 'Carlos', 'Augusto', 'Denis']
sorted_students = sorted(students)
print(sorted_students)
print(students)

> ['Augusto', 'Carla', 'Carlos', 'Daniela', 'Denis', 'José']
> ['José', 'Daniela', 'Carla', 'Carlos', 'Augusto', 'Denis']

reverse()

The reverse() function will reverse the order of the elements in a list. Just like the sort() function, it executes this operation permanently on the list, so take care whenever calling:

students.reverse()
print(students)

> ['José', 'Denis', 'Daniela', 'Daniela', 'Daniela', 'Carlos', 'Carla', 'Carla', 'Augusto']

in

Even though it is not a function, the in keyword is widely used with lists. We use it to verify if an item is in a list:

print("José" in students)
print("Felipe" in students)

> True
> False

split() and join()

These two functions have opposite purposes, and they actually operate in strings, but are strongly related with lists, which is why I’m including them here.

The split() function basically converts a string into a list. You can define the separator to be used. By default, the separator is a one space.

The join() function converts a list in a string, with its elements divided by a provided separator.

students_string = "; ".join(students)
print(students_string)
students_list = students_string.split("; ")
print(students_list)

> José; Denis; Daniela; Daniela; Daniela; Carlos; Carla; Carla; Augusto
> ['José', 'Denis', 'Daniela', 'Daniela', 'Daniela', 'Carlos', 'Carla', 'Carla', 'Augusto']

Conclusion

And, with this, we conclude our chapter about lists. We saw that lists are a structure to store different kinds of data. We also saw how to create, access data and modify a list. Finally, we saw a bunch of useful functions that can be used when you’re working with lists. In the next chapter, we will see a similar structure, the tuple.