Are you diving deeper into Python lists and wanting to learn about different ways to reverse them? If so, then this tutorial is for you. Here, you’ll learn about a few Python tools and techniques that are handy when it comes to reversing lists or manipulating them in reverse order. This knowledge will complement and improve your list-related skills and make you more proficient with them.
In this tutorial, you’ll learn how to:
- Reverse existing lists in place using
.reverse()and other techniques - Create reversed copies of existing lists using
reversed()and slicing - Use iteration, comprehensions, and recursion to create reversed lists
- Iterate over your lists in reverse order
- Sort your lists in reverse order using
.sort()andsorted()
To get the most out of this tutorial, it would be helpful to know the basics of iterables, for loops, lists, list comprehensions, generator expressions, and recursion.
Free Bonus: Click here to get a Python Cheat Sheet and learn the basics of Python 3, like working with data types, dictionaries, lists, and Python functions.
Reversing Python Lists
Sometimes you need to process Python lists starting from the last element down to the first—in other words, in reverse order. In general, there are two main challenges related to working with lists in reverse:
- Reversing a list in place
- Creating reversed copies of an existing list
To meet the first challenge, you can use either .reverse() or a loop that swaps items by index. For the second, you can use reversed() or a slicing operation. In the next sections, you’ll learn about different ways to accomplish both in your code.
Reversing Lists in Place
Like other mutable sequence types, Python lists implement .reverse(). This method reverses the underlying list in place for memory efficiency when you’re reversing large list objects. Here’s how you can use .reverse():
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> digits.reverse()
>>> digits
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
When you call .reverse() on an existing list, the method reverses it in place. This way, when you access the list again, you get it in reverse order. Note that .reverse() doesn’t return a new list but None:
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> reversed_digits = digits.reverse()
>>> reversed_digits is None
True
Trying to assign the return value of .reverse() to a variable is a common mistake related to using this method. The intent of returning None is to remind its users that .reverse() operates by side effect, changing the underlying list.
Note: Most of the examples in this tutorial use a list of numbers as input. However, the same tools and techniques apply to lists of any type of Python objects, such as lists of strings.
Okay! That was quick and straightforward! Now, how can you reverse a list in place by hand? A common technique is to loop through the first half of it while swapping each element with its mirror counterpart on the second half of the list.
Python provides zero-based positive indices to walk sequences from left to right. It also allows you to navigate sequences from right to left using negative indices:

This diagram shows that you can access the first element of the list (or sequence) using either 0 or -5 with the indexing operator, like in sequence[0] and sequence[-5], respectively. You can use this Python feature to reverse the underlying sequence in place.
For example, to reverse the list represented in the diagram, you can loop over the first half of the list and swap the element at index 0 with its mirror at index -1 in the first iteration. Then you can switch the element at index 1 with its mirror at index -2 and so on until you get the list reversed.
Here’s a representation of the whole process:

To translate this process into code, you can use a for loop with a range object over the first half of the list, which you can get with len(digits) // 2. Then you can use a parallel assignment statement to swap the elements, like this:
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for i in range(len(digits) // 2):
... digits[i], digits[-1 - i] = digits[-1 - i], digits[i]
...
>>> digits
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
This loop iterates through a range object that goes from 0 to len(digits) // 2. Each iteration swaps an item from the first half of the list with its mirror counterpart in the second half. The expression -1 - i inside the indexing operator, [], guarantees access to the mirror item. You can also use the expression -1 * (i + 1) to provide the corresponding mirror index.
Besides the above algorithm, which takes advantage of index substitution, there are a few different ways to reverse lists by hand. For example, you can use .pop() and .insert() like this:
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for i in range(len(digits)):
... last_item = digits.pop()
... digits.insert(i, last_item)
...
>>> digits
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In the loop, you call .pop() on the original list without arguments. This call removes and returns the last item in the list, so you can store it in last_item. Then .insert() moves last_item to the position at index i.
For example, the first iteration removes 9 from the right end of the list and stores it in last_item. Then it inserts 9 at index 0. The next iteration takes 8 and moves it to index 1, and so on. At the end of the loop, you get the list reversed in place.
Creating Reversed Lists
If you want to create a reversed copy of an existing list in Python, then you can use reversed(). With a list as an argument, reversed() returns an iterator that yields items in reverse order:
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> reversed_digits = reversed(digits)
>>> reversed_digits
<list_reverseiterator object at 0x7fca9999e790>
>>> list(reversed_digits)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In this example, you call reversed() with digits as an argument. Then you store the resulting iterator in reversed_digits. The call to list() consumes the iterator and returns a new list containing the same items as digits but in reverse order.
An important point to note when you’re using reversed() is that it doesn’t create a copy of the input list, so changes on it affect the resulting iterator:
>>> fruits = ["apple", "banana", "orange"]
>>> reversed_fruit = reversed(fruits) # Get the iterator
>>> fruits[-1] = "kiwi" # Modify the last item
>>> next(reversed_fruit) # The iterator sees the change
'kiwi'
In this example, you call reversed() to get the corresponding iterator over the items in fruits. Then you modify the last fruit. This change affects the iterator. You can confirm that by calling next() to get the first item in reversed_fruit.
If you need to get a copy of fruits using reversed(), then you can call list():
>>> fruits = ["apple", "banana", "orange"]
>>> list(reversed(fruits))
['orange', 'banana', 'apple']
As you already know, the call to list() consumes the iterator that results from calling reversed(). This way, you create a new list as a reversed copy of the original one.
Python 2.4 added reversed(), a universal tool to facilitate reverse iteration over sequences, as stated in PEP 322. In general, reversed() can take any objects that implement a .__reversed__() method or that support the sequence protocol, consisting of two special methods, .__len__() and .__getitem__(). So, reversed() isn’t limited to lists:
>>> list(reversed(range(10)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> list(reversed("Python"))
['n', 'o', 'h', 't', 'y', 'P']
Here, instead of a list, you pass a range object and a string as arguments to reversed(). The function does its job as expected, and you get a reversed version of the input data.
Another important point to highlight is that you can’t use reversed() with arbitrary iterators:
>>> digits = iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> reversed(digits)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'list_iterator' object is not reversible
In this example, iter() builds an iterator over your list of numbers. When you call reversed() on digits, you get a TypeError.
Iterators implement the .__next__() special method to walk through the underlying data. They’re also expected to implement the .__iter__() special method to return the current iterator instance. However, they’re not expected to implement either .__reversed__() or the sequence protocol. So, reversed() doesn’t work for them. If you ever need to reverse an iterator like this, then you should first convert it to a list using list().
Another point to note is that you can’t use reversed() with unordered iterables:
>>> digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> reversed(digits)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'set' object is not reversible
In this example, when you try to use reversed() with a set object, you get a TypeError. This is because sets don’t keep their items ordered, so Python doesn’t know how to reverse them.
Reversing Lists Through Slicing
Since Python 1.4, the slicing syntax has had a third argument, called step. However, that syntax initially didn’t work on built-in types, such as lists, tuples, and strings. Python 2.3 extended the syntax to built-in types, so you can use step with them now. Here’s the full-blown slicing syntax:
a_list[start:stop:step]
This syntax allows you to extract all the items in a_list from start to stop − 1 by step. The third index, step, defaults to 1, which is why a normal slicing operation extracts the items from left to right:
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> digits[1:5]
[1, 2, 3, 4]
With [1:5], you get the items from index 1 to index 5 - 1. The item with the index equal to stop is never included in the final result. This slicing returns all the items in the target range because step defaults to 1.
Note: You can omit the second colon (:) in a slicing operator when the default value (1) meets your current needs.
If you use a different step, then the slicing jumps as many items as the value of step:
>>> digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> digits[0::2]
[0, 2, 4, 6, 8]
>>> digits[::3]