Python offers several ways to reverse a list, and they do not have the same ownership or return behavior. list.reverse() changes the list in place and returns None. reversed(list) returns a reverse iterator without changing the original. list[::-1] creates a shallow copy in reverse order. Choose between mutation, iteration, and copying based on what the caller needs.
Quick answer
Use items.reverse() when you own the list and want to mutate it. Use list(reversed(items)) when you need a new list from a reverse iterator. Use items[::-1] for a concise shallow copy. Use reversed(items) directly when you only need to iterate backwards and do not need to store another list.
The official Python list documentation notes that in-place list methods return None. The reversed() documentation describes the iterator form. Those return contracts explain many bugs that appear when code assigns the result of reverse().

Reverse a list in place
The reverse() method reorders the existing list object. It is appropriate when the list is mutable state and all references to it should observe the new order. The method intentionally returns None, so call it as a statement.
items = [10, 20, 30, 40]
result = items.reverse()
print(items)
print(result)
A common mistake is items = items.reverse(). That assignment replaces the list reference with None. If the list should remain available, use the method on its own line and keep the original variable.

Create a reversed copy with slicing
The slice expression items[::-1] returns a new list whose elements are in reverse order. The original list is unchanged. This is convenient when the caller needs random access, a list length, or a value that can be passed to code expecting a concrete list.
items = [10, 20, 30, 40]
reversed_items = items[::-1]
print(items)
print(reversed_items)
print(items is reversed_items)
The copy is shallow. The list container is new, but nested objects are still shared. Reversing a list does not clone dictionaries, lists, or custom objects inside it.
Use reversed() for iteration
reversed(items) returns an iterator that yields items from the end toward the beginning. It does not create a second list and does not mutate the original. This is a good default for a one-pass loop.
items = ["first", "second", "third"]
for item in reversed(items):
print(item)
print(items)
An iterator is consumed as it is read. If the values must be traversed multiple times or indexed, materialize it with list(). Keeping the iterator lazy can save memory when the source is large.

Choose the return type deliberately
The three forms communicate different ownership decisions. The in-place method is fastest when mutation is intended. Slicing creates a list immediately. reversed() defers iteration and may work with other reversible objects, not only lists.
items = [1, 2, 3]
in_place = items.copy()
in_place.reverse()
copied = items[::-1]
iterator = reversed(items)
print(in_place)
print(copied)
print(list(iterator))
print(items)
Do not choose a form only because it is shorter. The return value and mutation behavior are part of the function contract. A helper that returns a new list is safer for general callers than a helper that silently changes a list it did not create.
Reverse strings and other sequences
Strings do not have a reverse() method because they are immutable, but slicing can return a reversed string. The same slice syntax works for tuples and other sequence types that support slicing. The meaning of reversing user-visible Unicode text may require more care than reversing code points.
word = "Python"
reversed_word = word[::-1]
print(reversed_word)
print(word)
For text with combining marks or emoji sequences, code-point reversal can produce visually incorrect output. If the user expects grapheme-cluster-aware reversal, use a library and a documented text model instead of assuming a slice matches what a person sees.

Reverse a list of records safely
When records are dictionaries or objects, a reversed list still contains references to the same records. A shallow copy is enough when order is the only change. Make a deep copy only when nested values must be independent, because deep copying can be expensive and may not be meaningful for every object.
records = [
{"id": 1, "name": "Ada"},
{"id": 2, "name": "Grace"},
]
reverse_order = list(reversed(records))
reverse_order[0]["name"] = "Grace Hopper"
print(records[1]["name"])
The example shows that the record dictionaries are shared. If a caller should not be able to modify the original records through the returned list, define that boundary explicitly and copy the records at the appropriate depth.
Reverse while enumerating
If an index is useful while iterating, enumerate the reversed iterator. The index produced by enumerate() starts at zero for the reversed traversal; it is not automatically the original list index. Compute the original index separately when that distinction matters.
items = ["a", "b", "c"]
for reverse_index, item in enumerate(reversed(items)):
original_index = len(items) - 1 - reverse_index
print(reverse_index, original_index, item)
This explicit calculation is easier to review than trying to infer an index from the loop order. It also works when the list length is known and the source is not modified during iteration.

Common mistakes
- Assigning the return value of
list.reverse()to the list variable. - Expecting
reversed()to return a list instead of an iterator. - Assuming
[::-1]deep-copies nested objects. - Mutating a list while an iterator over it is active.
- Reversing Unicode code points when the requirement is visual text reversal.
The pragmatic choice is simple: mutate with reverse(), lazily iterate with reversed(), or create a shallow copy with [::-1]. Make that choice explicit in the helper's name and return contract so callers know what happens to the original list.
Make the ownership contract visible
A function that returns a reversed list should usually leave its input unchanged unless mutation is the explicit purpose. Naming helpers with words such as copy, iterator, or in-place can make this contract obvious to callers. Tests should check both the returned order and the state of the original list.
When performance matters, measure the size of the data and the lifetime of the result. A reverse iterator avoids allocating another list, while a shallow copy makes later indexing and repeated iteration simpler. The right choice is a behavior decision before it is a micro-optimization.
For related list operations, compare list iteration with checking list length safely. Read python iterate through list and python list length for the related workflow.
Frequently Asked Questions
Frequently Asked Questions
How do I reverse a Python list?
Use items.reverse() to mutate the list, reversed(items) to iterate backward, or items[::-1] to create a reversed shallow copy.
Why does list.reverse() return None?
reverse() changes the existing list in place and returns None by design, so it should be called as a statement.
What does reversed() return?
reversed(items) returns an iterator that yields items from the end toward the beginning without changing the original list.
Does [::-1] make a deep copy?
No. It creates a new list container, but nested objects inside the list are still shared.