Python reversed vs reverse: Key Differences
Python provides two distinct ways to reverse sequences: the built-in
reversed() function and the list method
.reverse(). While both achieve a reversed order, they
differ fundamentally in how they operate on data, what they return,
their memory usage, and the data types they support. This article
explains how reversed() creates a memory-efficient iterator
without modifying the original data, while .reverse()
mutates a list in place and returns None, allowing you to
choose the correct tool for your specific use case.
1. In-Place Mutation vs. Non-Destructive Operation
The most critical distinction between these two options is whether the original object is modified.
list.reverse()is an in-place operation. It rearranges the elements directly inside the original list object in memory, permanently changing its order.reversed()is non-destructive. It leaves the original sequence untouched and generates a new sequence iterator.
# Using .reverse()
numbers = [1, 2, 3]
numbers.reverse()
print(numbers) # Output: [3, 2, 1] (original list is modified)
# Using reversed()
numbers = [1, 2, 3]
rev_iterator = reversed(numbers)
print(numbers) # Output: [1, 2, 3] (original list remains unchanged)2. Return Values
Because their operations differ, their return values are completely different:
list.reverse()returnsNone: Attempting to assign the result of.reverse()to a variable will storeNone. This is a common pitfall for beginners.reversed()returns an iterator: It returns a specialized reverse iterator object (e.g.,list_reverseiteratororreversedobject) that yields elements one by one upon request.
data = [10, 20, 30]
# .reverse() returns None
result = data.reverse()
print(result) # Output: None
# reversed() returns an iterator
rev_obj = reversed([10, 20, 30])
print(rev_obj) # Output: <list_reverseiterator object at 0x...>
print(list(rev_obj)) # Output: [30, 20, 10]3. Supported Data Types
list.reverse()is exclusively a list method: It cannot be used on tuples, strings, ranges, or dictionaries.reversed()works on any sequence: It accepts any iterable that implements the__reversed__()method or supports the sequence protocol (implements__len__()and integer-based__getitem__()).
# reversed() on a string
name = "Python"
print("".join(reversed(name))) # Output: "nohtyP"
# reversed() on a tuple
coords = (1, 2, 3)
print(tuple(reversed(coords))) # Output: (3, 2, 1)
# .reverse() fails on strings or tuples
# "Python".reverse() -> AttributeError: 'str' object has no attribute 'reverse'4. Memory and Performance
list.reverse()operates with \(O(1)\) auxiliary space complexity because it swaps elements within the existing array without allocating additional memory for elements.reversed()also uses \(O(1)\) auxiliary memory because it evaluates lazily. It does not create a full reversed copy in memory; instead, it tracks an index pointer backwards through the existing sequence.
However, if you convert the iterator produced by
reversed() into a concrete list using
list(reversed(seq)), it requires \(O(n)\) space to store the new list.
Comparison Summary
| Feature | list.reverse() |
reversed() |
|---|---|---|
| Type | Method of list |
Built-in function |
| Modifies Original? | Yes (In-place) | No |
| Return Value | None |
Reverse iterator |
| Supported Types | Lists only | Any sequence (lists, tuples, strings, etc.) |
| Memory Overhead | \(O(1)\) | \(O(1)\) (Iterator evaluation) |
When to Use Which
Use
.reverse()when:- You are working strictly with a list.
- You do not need to preserve the original order of the list.
- You want to avoid the minor overhead of instantiating an iterator.
Use
reversed()when:- You need to keep the original collection intact.
- You are working with immutable sequences such as strings or tuples.
- You only need to iterate over items in reverse order inside a
forloop without allocating a new list in memory:
# Efficient loop without mutating data or creating new lists
items = ["a", "b", "c"]
for item in reversed(items):
print(item)