Skip to content
Happy Programming Guide
Start learning
Python

Python’s reversed() for Reversing Ranges and Sequences

How reversed() works on ranges, lists and strings, why it returns an iterator rather than a list, and when slicing or .reverse() is the better choice.

Black pen and peach sticky notes rest on a silver laptop keyboard

reversed() returns an iterator that walks a sequence backwards. It does not create a reversed copy, which is why printing it shows an object rather than your data. On a range it is especially efficient — no values are generated until you ask for them, so reversing a range of ten million costs nothing.

The basics#

Python
numbers = [1, 2, 3, 4, 5]

print(reversed(numbers))          # <list_reverseiterator object at 0x...>
print(list(reversed(numbers)))    # [5, 4, 3, 2, 1]

for n in reversed(numbers):
    print(n)                      # 5 4 3 2 1

The first line is the thing that confuses people. reversed() is lazy — it produces values only as you consume them. In a for loop that is exactly what you want; to see or store the values, wrap it in list().

Reversing a range#

Python
for i in reversed(range(5)):
    print(i)                      # 4 3 2 1 0

for i in reversed(range(1, 11)):
    print(i)                      # 10 down to 1

for i in reversed(range(0, 20, 2)):
    print(i)                      # 18 16 14 ... 0

The equivalent with a negative step:

Python
for i in range(4, -1, -1):
    print(i)                      # 4 3 2 1 0

Both are correct and produce identical output. reversed(range(5)) is easier to read and much harder to get wrong — the negative-step version needs the stop value to be one past where you want to finish, which is a classic off-by-one source.

Python
range(5, 0, -1)      # 5 4 3 2 1  - does NOT include 0
range(4, -1, -1)     # 4 3 2 1 0  - does include 0

Three ways to reverse#

Method Returns Changes the original Memory
reversed(seq) an iterator no constant
seq[::-1] a new sequence no a full copy
list.reverse() None yes, in place constant
Python
numbers = [1, 2, 3]

a = list(reversed(numbers))    # [3, 2, 1], numbers unchanged
b = numbers[::-1]              # [3, 2, 1], numbers unchanged
c = numbers.reverse()          # c is None, numbers is now [3, 2, 1]

Which to choose#

  • Looping backwards? Use reversed(). It allocates nothing.
  • Need a reversed list or string to keep? Use slicing.
  • Want to reverse a list permanently? Use .reverse().
Python
big = list(range(10_000_000))

for n in reversed(big):        # no copy
    if n < 5: break

copy = big[::-1]               # allocates a second 10-million list

Strings#

Python
text = "hello"

print(text[::-1])                    # "olleh" - the usual way
print("".join(reversed(text)))       # "olleh" - same result, slower

Slicing is the idiomatic choice for strings. The reversed version has to build a list of characters and join them, which does more work for the same answer.

One caution: neither handles combining characters or emoji sequences correctly, because they reverse code points rather than what a reader sees as a character.

Python
print("café"[::-1])          # works - the accent is a single code point
print("👨‍👩‍👧"[::-1])            # breaks - a multi-code-point sequence

What can be reversed#

Python
reversed([1, 2, 3])          # list - fine
reversed((1, 2, 3))          # tuple - fine
reversed("abc")              # string - fine
reversed(range(5))           # range - fine
reversed({1: "a", 2: "b"})   # dict - fine in Python 3.8+, gives keys

reversed({1, 2, 3})          # TypeError - sets have no order
reversed(x for x in [1, 2])  # TypeError - generators cannot be reversed

A sequence must know its length and support indexing to be reversible. Sets and generators know neither, so you have to materialise them first:

Python
gen = (x * 2 for x in range(5))
print(list(reversed(list(gen))))     # [8, 6, 4, 2, 0]

Your own class#

Python
class Playlist:
    def __init__(self, tracks):
        self.tracks = tracks

    def __len__(self):
        return len(self.tracks)

    def __getitem__(self, index):
        return self.tracks[index]


p = Playlist(["a", "b", "c"])
print(list(reversed(p)))         # ['c', 'b', 'a']

Defining __len__ and __getitem__ is enough — Python builds the reverse iterator from them. Define __reversed__ only if you can do it more efficiently than that default.

The consumed-iterator bug#

Python
r = reversed([1, 2, 3])

print(list(r))     # [3, 2, 1]
print(list(r))     # []  - already exhausted
print(sum(r))      # 0

An iterator produces its values once. After the first list() walked through it, there is nothing left — and no error, just an empty result. If you need the values twice, store them.

Combining with other functions#

Python
names = ["ana", "sam", "kim"]

for i, name in enumerate(reversed(names)):
    print(i, name)               # 0 kim, 1 sam, 2 ana

# Index counting down instead
for i, name in zip(reversed(range(len(names))), reversed(names)):
    print(i, name)               # 2 kim, 1 sam, 0 ana

# Sorted descending - use sorted, not reversed
print(sorted(names, reverse=True))

That last line is worth noting: reversed(sorted(x)) and sorted(x, reverse=True) give the same result, but the second is clearer and does not build an intermediate list.

Questions people ask#

Why does printing reversed() show an object?

Because it is an iterator, not a list. It has produced nothing yet. Wrap it in list() to see the values.

Is slicing faster than reversed()?

For building a full reversed copy, slicing is faster. For iterating, reversed() wins because it allocates nothing.

Can I reverse a dictionary?

Since Python 3.8, reversed(d) gives the keys in reverse insertion order, and reversed(d.items()) gives the pairs. Before that, convert to a list first.

How do I reverse a list of lists?

reversed() reverses the outer list only. To reverse each inner list as well: [list(reversed(inner)) for inner in reversed(outer)].

Where to go next#

Generators and iterators, and why they are lazyRead next

Keep reading

Keep going — pick your next guide

The fastest way to improve is to read one guide, then build the thing it describes. Start with the basics, or jump straight to a project.

Ask a question or share what worked

Your email address will not be published. Required fields are marked *