Back to articles list Articles
8 minutes read

How to Loop Over Multiple Lists in Python

Learn how to loop over multiple lists side-by-side in Python – one element at a time. These techniques will work even if the lists have different lengths!

Looping over lists is one of the most basic skills in Python. In some situations, you may find yourself having to loop over multiple lists side-by-side, taking one element from each list and performing an operation with it. If you’re new to Python, it is not always obvious how to do that or what caveats and best practices exist for this task.

In this article, we’ll learn how to best loop over multiple lists in Python. We will start with a simple for loop, learn how to iterate over multiple lists “manually”, then explore the usefulness of the zip and zip_longest functions. You should be a bit familiar with sequences like tuples and lists and have a basic understanding of how looping works. If you need a refresher, check out the linked articles for some pointers. Otherwise, let’s get started!

Looping Over Lists in Python

Let’s recap how to iterate over a list in Python. The simplest way is to use a for loop to go through each element of the list. Here’s an example:

animals = ["cat", "dog", "monkey"]

for animal in animals:
    print(animal)

# output:
# cat
# dog
# monkey

The for loop goes over each animal in the animals list, places it in a variable called animal, and then prints it.

Another possibility is to directly access each element in the list by using its index. Normally, this involves creating a range of numbers up to the list’s length (the variable n in the example below), iterating through that range, then using each number as the index of each element in the list.

Here’s how it looks:

animals = ["cat", "dog", "monkey"]
n = len(animals)

for i in range(n):
    animal = animals[i]
    print(animal)

# output:
# cat
# dog
# monkey

Despite the differences in syntax, this iteration yields the exact same result as before. Since it is a bit more convoluted,  the for animal in animals loop is generally preferred when all you need is to iterate over a single list.

Manually Looping Over Multiple Lists in Python

So far, for loops are easy enough. But what happens if we have multiple lists to iterate over?

This issue comes up when we have data that’s related but stored in different lists. For example, consider the two lists below, students and grades:

students = ["John", "Mary", "Luke"]
grades = [9.0, 8.5, 7.5]

Even though they are separate lists, they are related by index: John (the first element in the students list) got a grade of 9.0 (the first element in the grades list), Mary got 8.5, and so on. How can we iterate over both lists and print out each student alongside their respective grade?

One solution is to use the index-based iteration that we used before. If we use the same index to take an element from each list, we end up with the appropriate pair of values. Here’s how it looks:

students = ["John", "Mary", "Luke"]
grades = [9.0, 8.5, 7.5]

n = len(students)

for i in range(n):
    student = students[i]
    grade = grades[i]
    print(student, "got a grade of", grade)

# output:
# John got a grade of 9.0
# Mary got a grade of 8.5
# Luke got a grade of 7.5

As you can see, each student is printed alongside their grade. Also, note how the list used when calculating n doesn’t really matter. It would have worked just the same if we wrote n = len(grades) instead.

The Problem With Using Indices

But wait – there’s a catch! What happens if the students and grades list do not have the same size? In that case, different things happen, depending on whether you use the shorter or longer list to generate the indices.

If the shorter list is provided, then the loop will end before the extra elements of the longer list are accessed. In the example below, note how the last grade is not accessed at all:

students = ["John", "Mary"]
grades = [9.0, 8.5, 7.5]

n = len(students)

for i in range(n):
    student = students[i]
    grade = grades[i]
    print(student, "got a grade of", grade)

# output:
# John got a grade of 9.0
# Mary got a grade of 8.5

On the other hand, if the longer list is used to calculate n, then the code will eventually run into an IndexError when attempting to take an element from the shorter list:

students = ["John", "Mary", "Luke", "Anna"]
grades = [9.0, 8.5, 7.5]

n = len(students)

for i in range(n):
    student = students[i]
    grade = grades[i]
    print(student, "got a grade of", grade)

# output:
# John got a grade of 9.0
# Mary got a grade of 8.5
# Luke got a grade of 7.5
# IndexError: list index out of range

When i is 3, students[i] becomes students[3] and returns the element "Anna". However, in that same iteration, no element exists for grades[3]. This results in the IndexError seen above.

Using the zip Function to Automatically Loop Over Multiple Lists

There’s a much simpler alternative for iterating over multiple lists in Python: the zip function. This is a built-in function that allows you to iterate over two or more lists side by side. (If you’re curious, we have a full course on Python’s built-in functions ready for you to explore.)

Compare the example below with our previous code and note just how much simpler and nicer it looks:

students = ["John", "Mary", "Luke"]
grades = [9.0, 8.5, 7.5]

for student, grade in zip(students, grades):
    print(student, "got a grade of", grade)

# output:
# John got a grade of 9.0
# Mary got a grade of 8.5
# Luke got a grade of 7.5

By using the zip function, we don’t need to worry about storing the list’s length in a variable like n or manually getting the elements using the index i. We simply put the lists we want to iterate over into the zip function and let Python worry about the details. Also, note how the variables student and grade refer to elements inside each list passed to the zip function in the same order.

You can also use the Python zip function to iterate over more than two lists side-by-side. Simply put them all in the zip function, then use the same number of variables in the for loop to store the respective elements of each list:

students = ["John", "Mary", "Luke"]
ages = [12, 10, 13]
grades = [9.0, 8.5, 7.5]

for student, age, grade in zip(students, ages, grades):
    print(student, "is", age, "years old and got a grade of", grade)

# output:
# John is 12 years old and got a grade of 9.0
# Mary is 10 years old and got a grade of 8.5
# Luke is 13 years old and got a grade of 7.5

Using the zip_longest Function to Reach All Elements in Multiple Lists in Python

What about lists that have a different number of elements in each one? Well, the zip function’s behavior is to simply stop iterating once all elements in the shortest list are visited. For example, the loop below only executes once because the list students only has a single entry in it:

students = ["John"]
ages = [12, 10, 13]
grades = [9.0, 8.5, 7.5]

for student, age, grade in zip(students, ages, grades):
    print(student, "is", age, "years old and got a grade of", grade)

# output:
# John is 12 years old and got a grade of 9.0

If you want to visit all elements in all lists, you can use the zip_longest function instead. This function resides in the itertools module that comes with Python’s standard library, so we only need to import it in order to use it.

As the name suggests, the zip_longest function works much like the regular zip function, but it reaches all elements – even those in the longest lists. To do that, it fills in values in the shorter lists with a default value. Here’s how it looks in action:

from itertools import zip_longest

students = ["John", "Mary", "Luke"]
ages = [12, 10]
grades = [9.0]

for student, age, grade in zip_longest(students, ages, grades, fillvalue="??"):
    print(student, "is", age, "years old and got a grade of", grade)

# output:
# John is 12 years old and got a grade of 9.0
# Mary is 10 years old and got a grade of ??
# Luke is ?? years old and got a grade of ??

As you can see, even though the lists ages and grades are shorter than students, we iterated over all elements of students. To make that possible, the shorter lists are padded with a “fill value” during the loop. By default, a None value is used as the fill value, but here we used the string "??" for a nicer formatting. Pretty handy!

Wrapping Up Python Loops, zip, and zip_longest

As we have seen, the zip and zip_longest functions really help when you need to loop over multiple lists in Python. With these functions, you do not have to worry about indices and list sizes and can focus on the looping process itself. Remember: use zip when you want your loop to stop after the shortest list is exhausted; use zip_longest if you want to access every element in the longer list.

Now you should be ready to loop over multiple Python lists, no matter their number or length. But don’t stop learning here – how about checking out our Python for Data Science Track to bump up your skill even further?