Python lists are a data collection type, which means that we can use them as containers for other values.
You can think of lists as exactly what lists are in real life: they contain items, which can be different types, and can even contain duplicates.
Think of the following grocery shopping list:
- Apples,
- Ground beef,
- Paper towels
In Python, we could define this list using square brackets []
. Let’s put this list together:
groceries = ['Apples', 'Ground Beef', 'Paper Towels']
What Python lists even more interesting is that they don’t always have to contain the same data type. For example, we could also include integers or booleans in our list. Additionally, we can include duplicate items.
Let’s change our list to include different data types, so that our list follows the format of: # of items, items, and whether this is accurate.
groceries = [3, ['Apples', 'Oranges'], True]
Properties of Python Lists
Now that you have defined a few lists, let’s take a look at some of the key propeties that make up Python lists.
Python lists are…
Indexing Lists to Select an Item
We can access an item or multiple items in a list by using the index (or indices). Because lists are ordered, we can make use of this property and use an item’s position to access its value.
Imagine we’re working with a list containing a rainbow’s colors. In Python, we can create this list by writing:
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
Because Python uses 0-based indexing (meaning indices start at 0, not 1), to access the first item we can use position 0
. In order to do this, we can use rainbow[0]
. Try printing the first color out below:
We can also access items in reverse. In this case, the last item can be accessed using the index position of -1
. Try printing out the last color of the rainbow using rainbow[-1]
in the code editor above.
Slicing Lists to Select Multiple Items
To select multiple items, we can slice a list. This works in much the same way as indexing a list, except that we pass in the beginning and end values separated by a colon. For example, if we wanted to select the first three items, we could write:
print(rainbow[0:3])
# Returns
# ['Red', 'Orange', 'Yellow']
Notice how we included 3
in our slice. The values go up to, but don’t include, the last value.
We can simplify that code even further – when we want to slice from the beginning, we can omit writing the 0
:
print(rainbow[:3])
# Returns
# ['Red', 'Orange', 'Yellow']
Similarly, we can select all values up to the last value by omitting the end value.
Selecting values to the end
Omitting the end value is especially helpful, since we often may not know how long a list is.
For example, our list of colours has seven items. So we would write rainbow[3:7]
to select the fourth through the seventh item. But writing rainbow[3:]
allows us not first to determine the list’s length.
We can even combine slicing with negative indexing. This allows us to, say, select the last three values by writing rainbow[-3:]
. Try selecting the second through the second last color below:
Modifying Lists with Assignments
Because lists are mutable, we can change the values within them. For example, we can assign a new value based on its index position or multiple values using a slice.
If we wanted to change the first color, we could do this by modifying the first index value:
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
rainbow[0] = "Black"
print(rainbow)
# Returns:
# ["Black", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
Similarly, we can modify multiple sequential values at once by modifying the slice of a list.
Say we wanted to change the last two colours to "Pink"
and "Brown"
, we could write:
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
rainbow[-2:] = ["Pink", "Brown"]
print(rainbow)
# Returns:
# ["Red", "Orange", "Yellow", "Green", "Blue", "Pink", "Brown"]
Notice how we assigned a list of values, rather than a single string.
Now it’s your turn – try to change the first two colors to different values:
When we try to modify a value that doesn’t yet exist, such as an eighth color of the rainbow, Python will throw an IndexError
. We’ll learn more about adding new items to lists later – for now, just know that this won’t work. Give it a shot and try assigning an eighth colour using the editor above.
Checking to See if an Item Exists in a List
In order to check if an item exists in a list or not, you can use the in
keyword. Because Python focuses on readability, we can use a plain English expression to check if an item exists or not:
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
print('Yellow' in colors)
# Returns:
# True
The keyword will return a boolean value indicating whether or not the value exists in the string or not:
True
is returned if the value exists, such as in the example above, andFalse
is returned if the value doesn’t exist
Because the statement will return a boolean, it tells us whether the value exists or not – not how often. For example, if a value existed a hundred times, it would still only evaluate to True
.
List Functions
Many different built-in functions can be used with Python lists. For example, you can check the length of a list using the len()
function.
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
print(len(colors))
# Returns:
# 7
There are many other useful functions. We can also use the sorted()
function to sort the values in a list:
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
print(sorted(rainbow))
# Returns:
# ['Blue', 'Green', 'Indigo', 'Orange', 'Red', 'Violet', 'Yellow']
Below, you’ll find a table of other functions you can use with lists:
Function | Description |
---|---|
len(lst) | Returns the number of elements in the list |
sum(lst) | Returns the sum of elements (only for numeric lists) |
min(lst) | Returns the smallest element |
max(lst) | Returns the largest element |
sorted(lst) | Returns a sorted copy of the list |
enumerate(lst) | Returns index-element pairs (often used in loops) |
all(lst) | Returns True if all elements are truthy |
any(lst) | Returns True if any element is truthy |
reversed(lst) | Returns a reverse iterator (use list() to see results) |
Let’s try some of these out. Because many of these work more logically on list with numerical values, let’s quickly shift to another list. Try finding the maximum value, the minimum value, and the sum of all the values.
List Methods
Python lists are objects, which means that they can store data and have methods that can act on that data.
What are methods?
Methods are functions that belong to objects and can operate on the data within those objects.
While functions like len()
can accept lists as arguments, methods act on the object itself—often to modify it or retrieve information about it.
Remember in an earlier section when we tried to add an eighth color using direct assignment? This failed and raised an IndexError
, indicating that that index value didn’t exist. This is where methods come into play – we can use methods to learn more about lists (such as counting how often an item exists) or modify a list (such as adding a new value).
Adding Items to Lists with .append()
and .extend()
We can add items to a list using the .append()
and .extend()
methods.
- The
.append()
method accepts a single item and adds it to the end of the list, and - The
.extend()
method accepts a list of values and extends the list with the items
Let’s take a look at how we can add a new color to our rainbow:
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
rainbow.append("Grey")
print(rainbow)
# Returns:
["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet", "Grey"]
Similarly, we can add multiple colors at once by passing a list of colors to the .extend()
method. Let’s add the colors ["Grey", "Neon Green"]
to our list:
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
rainbow.extend(["Grey", "Neon Green"])
print(rainbow)
# Returns:
["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet", "Grey", "Neon Green"]
It’s important to know when to use which method. While we can use the .extend()
method with a single string, you’ll run into some unexpected results. Try adding the color "Grey"
using the .extend()
method below:
Something unexpected happens! We end up with this list:
['Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Indigo', 'Violet', 'G', 'r', 'e', 'y']
The reason that this happens is the method expects an iterable. Because strings themselves are iterable, it splits the string into individual characters, appending each character individually.
We can learn more about methods by using the help()
function. Because methods are associated with any list object, we can call the help function using list.extend
or rainbow.extend
.
print(help(rainbow.extend))
# Returns:
# Help on built-in function extend:
#
# extend(iterable, /) method of builtins.list instance
# Extend list by appending elements from the iterable.
#
# None
We can see that the method expects an iterable (while calling this for the .append()
method would indicate an object)!
Removing Items from Lists with .pop()
and .remove()
We can also remove items from a list using different methods. For example, we can use:
- The
.pop()
method to remove an item by its position from a list (and return its value), and - The
.remove()
method to remove an item by its value
By default, the .pop()
method will remove and return the last value in a list. What does it mean to remove and return the value? Let’s give it a try below:
However, we can also use the .pop()
method to remove items based on their index position. By default, Python uses a -1
, which – as you now know – is the last item of the list.
We can modify this to remove and return the first item, however, by passing in the index position of 0
.
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
popped_value = rainbow.pop(0)
print("The list is now: ", rainbow)
print("The popped value of the list was: ", popped_value)
# Returns:
# The list is now: ['Orange', 'Yellow', 'Green', 'Blue', 'Indigo', 'Violet']
# The popped value of the list was: Red
The .pop()
method is useful when you need to remove and item and use it. In most cases, you’ll use it to remove items from the back of a list, such as in a stack data structure.
Being mindful of popping from the left
You might find popping items from the left a tempting option. This can be useful to create a queue, or a first-in-first-out (FIFO) data structure. Each time you pop from the left using list.pop(0)
, Python processes this is by shifting all list items to the left. Doing this with large lists can cause performance issues.
While out of scope for this tutorial, this would be a useful time to use the deque
object from the built-in collections
module.
We can use the .remove()
to remove an item by its value. The method will look for the first instance of that value and remove it from the list.
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
rainbow.remove("Yellow")
print("The list is now: ", rainbow)
# Returns:
# The list is now: ['Red', 'Orange', 'Green', 'Blue', 'Indigo', 'Violet']
The method will raise a ValueError
when we try to remove an item that doesn’t exist.
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
rainbow.remove("Grey")
# Raises:
# ValueError: list.remove(x): x not in list
Because of this, it can be helpful to first check if an item exists or not, using the in
key:
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
if 'Grey' in rainbow:
rainbow.remove("Grey")
else:
print("Grey is not in the list")
# Returns:
# Grey is not in the list
Another important thing to note is that the method will only remove the first instance of that item in a list. If the item exists more than once, only the first instance will be removed.
As a challenge, try the following scenarios below:
- Remove the number 1
- Remove the last item
- Remove all instances of the number 3
Iterating over Lists
There will be times when you need to access each item in a list. In these cases, it’s helpful to iterate over the list.
The easiest way to do this is by using a for loop, which allows us to do an action for each item in a list.
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
for color in rainbow:
print(color)
# Returns:
# Red
# Orange
# Yellow
# Green
# Blue
# Indigo
# Violet
Our choice of the term color
doesn’t matter – we could choose to use any term we wanted. However, because Python prioritizes readability, it makes sense to use a term that increases readability. It’s best practice not to use random letters like a
since these don’t help readability.
In our previous example, we simply printed out each value in the list. However, we can also do something with each item in the list. For example, we can print out the length of each value by using the len()
function.
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
for color in rainbow:
print(color, len(color))
# Returns:
# Red 3
# Orange 6
# Yellow 6
# Green 5
# Blue 4
# Indigo 6
# Violet 6
Now it’s your turn – try to print each item in uppercase using the .upper()
string method.
We can also use for loops to create new lists based on other lists. So far, we have only printed out values (or modified values) from our lists. However, if we wanted to store these modified values, we could create a new list.
Let’s recreate the challenge from above and add the new values to a new list:
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
upper_rainbow = []
for color in rainbow:
upper_rainbow.append(color.upper())
print(upper_rainbow)
# Returns:
# ['RED', 'ORANGE', 'YELLOW', 'GREEN', 'BLUE', 'INDIGO', 'VIOLET']
To accomplish this, we first created an empty list. We then looped over each item in our list and appended the .upper()
version of that string to the list.
List Comprehensions
List comprehensions provide a simple way to create new lists in Python. In the previous example, we used a for loop to create a new list. However, we can simplify this by using a list comprehension.
List comprehensions use a simple syntax:
[expression for item in list]
Where:
expression
is what you want to do with each item,item
is the variable that represents each element in the iterable, anditerable
is the data you’re looping through.
How could we recreate our earlier example? Let’s take a look:
rainbow = ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
upper_rainbow = [color.upper() for color in rainbow]
print(upper_rainbow)
# Returns:
# ['RED', 'ORANGE', 'YELLOW', 'GREEN', 'BLUE', 'INDIGO', 'VIOLET']
We can see that the list comprehension format is much more concise than using a for loop. For example, we don’t first need to create an empty list.
On the other hand, list comprehensions can feel complex for beginners and can become much more complex as the logic evolves.
As a challenge, use a list comprehension to get the square of each value. In Python, you can square a number by using the exponentiation **
operator: