HOWTO · Python

How to Iterate Backwards in Python

This article discusses how to iterate backwards in Python, exploring various methods like the reversed() function, list slicing, while loops, and enumerate. With clear code examples and detailed explanations, you'll learn to efficiently traverse data structures in reverse order, enhancing your programming skills and versatility.

On this page

Iterating backward means visiting a sequence from its last item to its first. Python offers several ways to do this, and the right choice depends on whether you need only the values, need to change the sequence, or need each item’s original index. The examples below use lists, but reversed() and slicing also work with strings and tuples.

Using reversed() to Iterate Backward

Use reversed() when you want to read a sequence from end to beginning without changing it. It returns an iterator, so it does not build a second list of the values. The source list remains in its original order.

Run this example:

items = ["first", "second", "third"]
for item in reversed(items):
    print(item)
third
second
first

This is a good default for a sequence when you only need to process its values in reverse. The iterator is consumed as the loop advances; if you need to traverse it again, call reversed(items) again. The sequence must support reverse iteration.

Iterating Backward with range() in Python

Use range() when the loop needs numeric positions, such as when you must update elements by index. Its arguments are range(start, stop, step). A negative step counts downward, and the stop value is excluded. For example, range(10, 0, -1) yields 10 through 1; range(10, -1, -1) yields 10 through 0.

items = ["first", "second", "third"]
for index in range(len(items) - 1, -1, -1):
    print(index, items[index])

The first index is len(items) - 1, the last valid position. The stop is -1 so that the loop includes index 0 before stopping. A common mistake is to use range(len(items) - 1, 0, -1), which skips index 0 because range() never includes its stop.

Reversing a Sequence with Slicing

A slice with a step of -1, written items[::-1], creates a new list with the items in reverse order. You can then loop over that list or keep it for later use.

items = ["first", "second", "third"]
backward = items[::-1]
print(backward)

Unlike reversed(), slicing allocates a reversed copy. That is useful when you need to keep the reversed values, but it uses additional memory proportional to the sequence length. Choose reversed() when you only need to visit the items; choose slicing when you need a separate reversed sequence.

Using a while Loop

A while loop gives direct control over the index and the work done between iterations. Start at the last valid index, process that item, then decrement the index. Make sure the loop condition includes index 0 and that the index changes on every pass; otherwise the loop may stop too soon or fail to make progress.

items = ["first", "second", "third"]
index = len(items) - 1
while index >= 0:
    print(items[index])
    index -= 1

This pattern is useful when the loop’s stopping rule or index updates are part of a larger algorithm. For a simple reverse traversal, reversed() is usually shorter and makes the intent clearer. The while form also handles a list with no items: its initial index is -1, so the loop body does not run.

Keeping Original Indices with enumerate()

enumerate() normally counts from zero as it traverses an iterable. To pair reverse-ordered values with their positions in the original list, enumerate reversed(items) and convert each reverse offset back to an original index.

items = ["first", "second", "third"]
for reverse_offset, item in enumerate(reversed(items)):
    original_index = len(items) - 1 - reverse_offset
    print(original_index, item)

The first reverse offset is 0, which maps to the last original index. Each next offset maps one position earlier. This approach avoids making a reversed list and is handy when you need both the values and their original positions. If you only need an index for lookup or assignment, the range() pattern is more direct.

Choosing a Method

Use reversed(sequence) for a clear, memory-efficient pass over values in reverse. Use range(len(sequence) - 1, -1, -1) when the loop needs to work with indices. Use sequence[::-1] when you need a separate reversed copy and the extra memory is acceptable. Use a while loop when custom index control is central to the algorithm. Combine enumerate(reversed(sequence)) with an index calculation when you need reverse-ordered values and their original positions.

For strings, these same choices apply because a string is a sequence: reversed(text) visits its characters backward, while text[::-1] creates a reversed string. These approaches concern sequence order; do not assume that they provide a general reverse traversal for every container. Pick the method that expresses what the loop needs, and account for whether it creates a copy or exposes original indices.