How to Reverse a List in Python?

5/5 - (1 vote)

Summary: There are only three best ways to reverse the order of the list elements:

• `list.reverse()` — Best if you want to reverse the elements of list in place.
• `list[::-1]` — Best if you want to write concise code to return a new list with reversed elements.
• `reversed(list)` — Best if you want to iterate over all elements of a list in reversed order without changing the original list.

The method `list.reverse()` can be 37% faster than `reversed(list)` because no new object has to be created.

When I read over code from my students, I often realize that they know one or two ways of solving a problem—but they don’t know which way is the best one for a particular problem. In this article, you’ll learn how to reverse a list—and which is the most Pythonic way in a given problem setting. So, let’s dive right into it!

Problem: Given a list of elements. How to reverse the order of the elements in the (flat) list.

Example: Say, you’ve got the following list:

`['Alice', 'Bob', 'Carl', 'Dora']`

Your goal is to reverse the elements to obtain the following result:

`['Dora', 'Carl', 'Bob', 'Alice']`

There are multiple ways to reverse a list. Here’s a quick overview:

Exercise: Run the code. In which case would you use the third method? Does it have any advantage compared to the first one?

Let’s dive into each of the methods in greater detail!

Method 1: Reverse a List In-Place with list.reverse()

To reverse a list in place and change the order of the elements in the original list, use the `list.reverse()` method. As the original list is modified and no new list is returned, this method has side effects which may (or may not) be what you need.

```# Method 1: list.reverse()
names = ['Alice', 'Bob', 'Carl', 'Dora']
names.reverse()
print(names)
# ['Dora', 'Carl', 'Bob', 'Alice']```

The order of the elements of the original list in the variable `names` has reversed.

Method 2: Reverse a List with Slicing [::-1]

Slicing is a concept to carve out a substring from a given string.

Use slicing notation `s[start:stop:step]` to access every `step`-th element starting from index `start` (included) and ending in index `stop` (excluded).

All three arguments are optional, so you can skip them to use the default values (`start=0`, `stop=len(lst)`, `step=1`). For example, the expression `s[2:4]` from string `'hello'` carves out the slice `'ll'` and the expression `s[:3:2]` carves out the slice `'hl'`.

You can use a negative step size (e.g., -1) to slice from the right to the left in inverse order. Here’s how you can use this to reverse a list in Python:

```# Method 2: Reverse a List with Slicing
names = ['Alice', 'Bob', 'Carl', 'Dora']
names = names[::-1]
print(names)
# ['Dora', 'Carl', 'Bob', 'Alice']```

This method is most concise and highly performant because the slice has an efficient memory representation. That’s why expert coders will often prefer slicing with negative step size over the `list.reverse()` method.

Method 3: Reverse a List with Iterator reversed(list)

The `list.reverse()` method reverses a list in place (it’s a method—and methods tend to modify the objects on which they are called). But what if you want to reverse a list and return a new list object? While you can use slicing for this, an even better way is to use the reversed(list) built-in Python function.

The `reversed()` function has one big advantage over slicing: it returns an iterator object rather than a full-fledged list. Compared to a list, an iterator has a more memory-friendly representation and if you don’t need a list, it’s usually best to live with an iterator (e.g., to iterate over all elements in reverse order).

```# Method 3: reversed()
names = ['Alice', 'Bob', 'Carl', 'Dora']
names = reversed(names)
print(list(names))
# ['Dora', 'Carl', 'Bob', 'Alice']```

However, in this code snippet, you actually want a list so you need to convert the iterator to a list using the `list(...)` constructor. In this case, it’s better to use slicing `names[::-1]` as shown in the previous method.

Method 4: Reverse a List with Indexing and a Simple Loop

Beginner coders and coders coming from other programming language often like to use indexing schemes to manipulate sequence elements (they don’t know better). For comprehensibility, I wanted to include the following method to reverse a list using nothing but simple indexing, a for loop, and the `range()` function.

```names = ['Alice', 'Bob', 'Carl', 'Dora']
l = []
for i in range(len(names)-1, -1, -1):
l.append(names[i])
print(l)
# ['Dora', 'Carl', 'Bob', 'Alice']```

The `range(len(names)-1, -1, -1)` function returns an iterator that starts with the index `len(names)-1` which is the last index in the variable `names`. It goes all the way to 0 (inclusive) using negative step size -1.

Method 5: Reverse a List with Negative Indexing

The previous code snippet can be optimized (in my opinion) by using negative indexing. In any way, it’s good if you know how to properly use negative indexing in Python—that is—to access the elements from the right rather than from the left.

Here’s how you can leverage negative indexing to access the elements in reverse order in a basic for loop:

```# Method 5: Negative Indexing
names = ['Alice', 'Bob', 'Carl', 'Dora']
l = []
for i in range(1, len(names) + 1):
l.append(names[-i])
print(l)
# ['Dora', 'Carl', 'Bob', 'Alice']```

Note that the last value taken on by variable `i` is `i=4`. Used as a negative index, you access the element `names[-4] == Alice` last.

Performance Evaluation

Let’s compare the speed of those five methods!

In the following code, you compare the runtime of each of the five methods to reverse a list with five elements and print the time it takes to execute it 10,000 times to the shell.

Exercise: Click “Run” and see which methods wins in your browser! How long does it take to reverse a list with 100,000 elements?

You can also copy&paste the code and run it on your computer:

```def reverse1():
names = ['Alice', 'Bob', 'Carl', 'Dora']
names.reverse()

def reverse2():
names = ['Alice', 'Bob', 'Carl', 'Dora']
names = names[::-1]

def reverse3():
names = ['Alice', 'Bob', 'Carl', 'Dora']
names = reversed(names)

def reverse4():
names = ['Alice', 'Bob', 'Carl', 'Dora']
l = []
for i in range(len(names)-1, -1, -1):
l.append(names[i])

def reverse5():
names = ['Alice', 'Bob', 'Carl', 'Dora']
l = []
for i in range(1, len(names) + 1):
l.append(names[-i])

import timeit
print('M1: ', timeit.timeit(reverse1, number=10000), '--> list.reverse()')
print('M2: ', timeit.timeit(reverse2, number=10000), '--> slicing')
print('M3: ', timeit.timeit(reverse3, number=10000), '--> reversed()')
print('M4: ', timeit.timeit(reverse4, number=10000), '--> loop')
print('M5: ', timeit.timeit(reverse5, number=10000), '--> loop + negative index')```

The most performant method on my computer is the `list.reverse()` method:

```M1:  0.0012140999999999957 --> list.reverse()
M2:  0.0016616999999999882 --> slicing
M3:  0.0019155999999999618 --> reversed()
M4:  0.005595399999999973 --> loop
M5:  0.006663499999999989 --> loop + negative index```

It’s interesting to see that the least readable and least concise methods 4 and 5 are also slowest! Note that we didn’t convert the iterator returned by the `reversed()` method to a list—otherwise, it would have added a few milliseconds to the result.

While this is not a scientific performance evaluation, it indicates that “standing on the shoulders of giants” by reusing existing code is usually a good idea!

Conclusion

There are only three best ways to reverse the order of the list elements:

• `list.reverse()` — Best if you want to reverse the elements of list in place.
• `list[::-1]` — Best if you want to write concise code to return a new list with reversed elements.
• `reversed(list)` — Best if you want to iterate over all elements of a list in reversed order without changing the original list.

You have seen in the evaluation that the method `list.reverse()` can be 37% faster than `reversed(list)` because no new object has to be created.

Where to Go From Here?

Enough theory. Let’s get some practice!

Coders get paid six figures and more because they can solve problems more effectively using machine intelligence and automation.

To become more successful in coding, solve more real problems for real people. That’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

You build high-value coding skills by working on practical coding projects!

Do you want to stop learning with toy projects and focus on practical code projects that earn you money and solve real problems for people?

🚀 If your answer is YES!, consider becoming a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

If you just want to learn about the freelancing opportunity, feel free to watch my free webinar “How to Build Your High-Income Skill Python” and learn how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!