avatarGonçalo Guimarães Gomes

Summarize

The Anatomy of Python Lists

An easy guide to summarize the most common methods and operations regarding list manipulation in Python.

Photo by Dmitry Ratushny on Unsplash

Python lists are a built-in type of data used to store items of any data type such as strings, integers, booleans, or any sort of objects, into a single variable.

Lists are created by enclosing one or multiple arbitrary comma-separated objects between square brackets.

Lists may contain elements of different data types

The items of a list can all be of the same or different data types.

a_list = [15.1, 'x', 14, True]
# The assigned variable ‘a_list’ contains a float, a string, an int, and a bool

List items follows a sequenced or specific order

The order in which the elements are disposed of is set when the list is written and if unchanged it will remain that way.

a_list = [15.1, 'x', 14, True]
b_list = [6.6, 2.0, 125, 0, 63]
c_list = ['London', 'Lisbon', 'New York', 'Sidney']

Access values by index

Like accessing characters in a string, each item in a list has an assigned index that can be accessed using square brackets. Keep in mind that list indexing is zero-based meaning that the first item is at index 0.

# Defining a list
a_list = [15.1, 'x', 14, True]
# Accessing the first value at index 0
a_list[0]
>>> output: 
15.1
---
# Accessing the second value at index 1
a_list[1]
>>> output: 
'x'

Accessing values can also be performed by negative indexing, that is, counts from the end of the list. This could be very handy when you need to access the last item without knowing the length of the list.

Index vs. negative indexing. Image by author
# Accessing the last value at index -1
a_list[-1]
>>> output:
True
---
# Accessing the first value at index -4
a_list[-4]
>>> output:
15.1

Slicing lists

Slicing is a great way of getting a subset of the list. For example, a_list[m:n] returns the subset of a_list from index[m] to index[n], not included. You can omit the index in case of index zero (0) or if extending the slice to the infinite. Let’s make it work in the next examples.

Accessing the list with index-slicing. Image by author

Understanding:

# Defining a list
a_list = [15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]
# You can omit the index in case of:
# a) index zero (0)
# Starts at the first character (index 0) and ends at the third (index 2), not included
a_list[:2]
>>> output:
[15.1, 'x']
# Starts at the second character (index 1) and ends at the fifth (index 4), not included
a_list[1:4]
>>> output:
['x', 14, 'London']
# Starts at the sixth character (index 5) and extends to the end of the list
a_list[5:]
>>> output:
[2.0, 'Lisbon', 0]
---
# You can also omit the index in case of:
# b) extending the slice to the infinite
# Extending to the infinite on both ends returns the whole list
a_list[:]
>>> output:
[15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]

Working a few examples slicing lists combining both positive and negative indices.

Accessing the list with negative index-slicing. Image by author

Understanding:

# The list
a_list = [15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]
# Returns the list counting every two characters
a_list[-5:-2]
>>> output:
['London', True, 2.0]
---
# Starts at index -4 and until the end of the list
a_list[-4:]
>>> output:
[True, 2.0, 'Lisbon', 0]
---
# Starts at index 2 and ends at index -3 (same as index 5, excluded)
a_list[2:-3]
>>> output:
[14, 'London', True]
---
# Starts at index -7 (same as index 1) and ends at index 6, excluded
a_list[-7:6]
>>> output:
['x', 14, 'London', True, 2.0]
---
# Returns the list from the beginning to index -5 (same as index 3, not included)
a_list[:-5]
>>> output:
[15.1, 'x', 14]

We can define a step in which it will ‘jump’ the number of specified characters in the third parameter.

# The list
a_list = [15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]
# Returns the whole list every two characters
​a_list[::2]
>>> output:
[15.1, 14, True, 'Lisbon']

The step can be either positive or negative.

# Goes to the infinite on both ends and returns the list on backwards every 3 characters
a_list[::-3]
>>> output:
[0, True, 'x']

Let’s make it work with a few examples slicing lists combining both positive and negative indices and steps.

# The list
a_list = [15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]
# Starts at index 0, ends at index -3 (same as index 5) every two characters
a_list[:-3:2]
>>> output:
[15.1, 14, True]
---
# Starts at index -2 (same as index 6), ends at index 2 (same as index -6) and returns the list on backwards
a_list[-2:2:-1]
>>> output:
['Lisbon', 2.0, True, 'London']
---
# Returns the whole list
a_list[::]
>>> output:
[15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]
---
# Returns the list on backwards every two characters
a_list[::-2]
>>> output:
[0, 2.0, 'London', 'x']

Although throughout the above examples our list was always assigned to a variable (a_list), it is possible to operate on a list literal as well.

[15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0][3]
>>> output:
'London'
---
[15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0][::-2]
>>> output:
[0, 2.0, 'London', 'x']
---
'Lisbon' in [15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]
>>> output:
True
---
len([15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0])
>>> output:
8

Nested lists

We realize a list can contain a collection of data of any type. This also includes another list, which can in turn contain another sublist itself, and so on to the infinite.

Nested lists. Image by author

Understanding:

# The list
n_list = [15.1, 6, ['apple', ['abc', 'xpto', 'zed']]]
# n_list[0] is a float and n_list[1] is an integer
print(n_list[0])
print(n_list[1])
>>> output:
15.1
6
---
# n_list[2] is a sublist
n_list[2]
>>> output:
['apple', ['abc', 'xpto', 'zed']]
---
# To access the items inside a sublist, must add another index to the first one
n_list[2][1]
>>> output:
['abc', 'xpto', 'zed']
---
# To access a specific character inside a sublist, you must apply the same reasoning of append additional indices as deep as desired
n_list[2][1][0]
>>> output:
'abc'
---
# Deep further, there is no limit
n_list[2][1][0][2]
>>> output:
'c'

From this point on it is easy to apply to sublists all the seen syntax regarding indices and slicing.

# The list
n_list = [15.1, 6, ['apple', ['abc', 'xpto', 'zed']]]
n_list[2][1][:2]
>>> output:
['abc', 'xpto']
---
n_list[2][1][::-1]
>>> output:
['zed', 'xpto', 'abc']
---
n_list[2][1][-1]
>>> output:
'zed'
---
n_list[2][1][-1][::-1]
>>> output:
'dez'

Lists are mutable

We can create a list and assign it into a variable and name it as a_list, for instance. Once the list is created we can now perform a bunch of modifications at will. Say that we can add any items, delete them, or move things around.

Let’s modify the list by adding some single values replacing the existing ones.

# The list
a_list = [15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]
# Adding a string (with a single character) at index 0 replacing the current value
a_list[0] = 'y'
# Adding a boolean at the last index and replace the current item
a_list[-1] = False
# Calling the variable
a_list
>>> output:
['y', 'x', 14, 'London', True, 2.0, 'Lisbon', False]

Let’s now modify the list by adding and replacing multiple items.

# The list
a_list = [15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]
# Checking values at indices two to six, excluded
a_list[2:6]
>>> output:
[14, 'London', True, 2.0]
---
# Assigning a single value from indices two to six
a_list[2:6] = [999]
a_list
>>> output:
[15.1, 'x', 999, 'Lisbon', 0]
# The number of items added is not equal to the number of items replaced and that is not a problem for python, it simply grows and shrinks the list along with the operations
a_list[2:3]
>>> output:
[999]
---
# Assigning values from indices two to three and replacing the 999 int
a_list[2:3] = ['x', 'p', 't', 'o']
a_list
>>> output:
[15.1, 'x', 'x', 'p', 't', 'o', 'Lisbon', 0]
# If we determine to replace at a specific index instead a slice, a sublist will be created
a_list[2] = ['a', 'b', 'c']
a_list
>>> output:
[15.1, 'x', ['a', 'b', 'c'], 'p', 't', 'o', 'Lisbon', 0]

It is possible to add any items without replacing the existing ones by specifying a slice with no length at the desired index.

# The list
a_list = [15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]
# Assigning elements without replacing any with a zero-length slice
a_list[2:2] = ['cat', 'dog']
a_list
>>> output:
[15.1, 'x', 'cat', 'dog', 14, 'London', True, 2.0, 'Lisbon', 0]

It is as easy to delete multiple items as it is to add them.

# The list
a_list = [15.1, 'x', 14, 'London', True, 2.0, 'Lisbon', 0]
# Checking sliced items
a_list[1:7]
>>> output:
['x', 14, 'London', True, 2.0, 'Lisbon']
# Assigning an empty list at the desired slice
a_list[1:7] = []
a_list
>>> output:
[15.1, 0]

Next, we’ll learn some common methods to manipulate and modify lists. For starters, adding elements.

Append

The .append() method will add a single value to the end of a list. This happens in place, therefore it doesn’t return any output.

# Defining a list
a_list = [15.1, 'x', 14, '7']
# Adding a value
a_list.append(5.5)
a_list
>>> output: 
[15.1, 'x', 14, '7', 5.5]

Keep in mind that when appending a list, this whole new list is added as one single element, instead appending each of its values.

# Appending a new list to the assigned 'a_list'
a_list.append(['abc', 12.6])
a_list
>>> output: 
[15.1, 'x', 14, '7', 5.5, ['abc', 12.6]]

On the other hand, if you want to add another list and combine all the items to the previous list, you need to use the .extend() method.

Extend

The .extend() method will add several values to a list. This means that when extending a list with another list all the values are added separately.

a_list = [15.1, 'x', 14, '7']
a_list.extend(['abc', 12.6])
a_list
>>> output: 
[15.1, 'x', 14, '7', 'abc', 12.6]
---
a_list = [15.1, 'x', 14, '7']
b_list = ['python', 7.7, 6]
a_list.extend(b_list)
a_list
>>> output: 
[15.1, 'x', 14, '7', 'python', 7.7, 6]

When using the + operator we get the same result.

a_list = [15.1, 'x', 14, '7']
b_list = ['python', 7.7, 6]
a_list + b_list
>>> output: 
[15.1, 'x', 14, '7', 'python', 7.7, 6]

Insert

The .insert() method adds an item in a specified index position.

a_list = [15.1, 'x', 14, '7']
# The first argument is the index and the second one is the value
a_list.insert(2, 'python')
a_list
>>> output: 
[15.1, 'x', 'python', 14, '7']

There are many ways to delete or remove elements from lists as follows.

Remove

The .remove() method will remove a desired element of a list (the first occurrence if repeated).

a_list = [15.1, 'x', 14, '7']
a_list.remove('x')
a_list
>>> output: 
[15.1, 14, '7']

Del

The .del() method will remove any element from a list according to its index.

a_list = [15.1, 'x', 14, '7']
del a_list[2]
a_list
>>> output: 
[15.1, 'x', '7']

Pop

The .pop() method removes an item at a specific index - if not specified, it will remove the last item by default (this operation returns the popped item).

a_list = [15.1, 'x', 14, '7']
print(a_list.pop(0))
print(a_list.pop(-1))
>>> output: 
15.1
7

It is possible to execute the .pop() method assigning it to a different variable.

a_list = [15.1, 'x', 14, '7']
b = a_list.pop()
print(a_list)
>>> output: 
[15.1, 'x', 14]

Clear

The .clear() method will erase all elements.

a_list = [15.1, 'x', 14, '7']
a_list.clear()
a_list
>>> output: 
[]

Sort

The .sort()method will sort the list in ascending order by default, although one can use the (reverse=True) parameter.

This method takes changes in place. This means that it doesn’t return anything.

a_list = [15.1, 5, 14, 7.8]
a_list.sort()
a_list
>>> output: 
[5, 7.8, 14, 15.1]

Sorted

On the other hand, if you want to keep the original list and sort the elements into a new list, you can use the built-in sorted function.

a_list = [15.1, 5, 14, 7.8]
sorted(a_list)
>>> output: 
[5, 7.8, 14, 15.1]
a_list
>>> output: 
[15.1, 5, 14, 7.8]
---
# you can keep the original list and create a sorted version of it
sorted_list = sorted(a_list)
display(a_list, sorted_list)
>>> output:
[15.1, 5, 14, 7.8]
[5, 7.8, 14, 15.1]

copy

The .copy() method will create a copy of the existing list.

a_list = [15.1, 'x', 14, '7']
b_list = a_list.copy()
# If we make any change in a_list, it won't reflect on the b_list
a_list.append('pandas')
display(a_list, b_list)
>>> output: 
[15.1, 'x', 14, '7', 'pandas']
[15.1, 'x', 14, '7']

A list can also be copied by selecting all its indices.

a_list = [15.1, 'x', 14, '7']
b_list = a_list[:]
# Again, if we make any change in a_list, it won't reflect on the b_list
a_list.extend(["pandas", "sklearn"])
display(a_list, b_list)
>>> output:
[15.1, 'x', 14, '7', 'pandas', 'sklearn']
[15.1, 'x', 14, '7']

Count

The .count() method will return how many matching elements there are.

a_list = [15.1, 'x', 14, 'x']
a_list.count('x')
>>> output:
2

Index

The .index() method will return the first (in case of repeated) index position of a desired value.

a_list = [15.1, 'x', 14, 'x']
a_list.index('x')
>>> output:
1

Len

The built-in len() function returns the number of elements in a list.

a_list = [15.1, 'x', 14, '7']
len(a_list)
>>> output:
4

reverse()

The .reverse()method will invert the order of the items in a list (the operation occurs in place so nothing is returned).

python_list.reverse()
print(python_list)
>>> output: 
['g', 'n', 'i', 't', 's', 'i', 'l']

Creating a list by splitting a string

string_text = "we all love python"
list_from_string = string_text.split(' ')
print(list_from_string)
>>> output:
['we', 'all', 'love', 'python']

Creating a list from the characters of a string

python_list = list("listing")
print(python_list)
>>> output: 
['l', 'i', 's', 't', 'i', 'n', 'g']

Check out other articles you might also like to read:

Conclusion

Now that we got the basics of lists’ manipulation, it becomes easy to realize how simple and powerful it is to perform some of the basic and extremely useful tasks using this type of data structure in Python.

We now have a solid and somehow deep understanding of some of its fundamental characteristics:

  • Lists may contain elements of different data types
  • List items follow a specific order
  • Its values can be accessed by index and slicing
  • Items can be added, removed, and transformed which makes them mutable and dynamic.

Thank you for reading. You are welcome to comment below and please let me know if you have any feedback.

Python List
Python
Tutorial
List Manipulation
Python Programming
Recommended from ReadMedium