Print a list in reverse order with range?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Printing a list in reverse order is a common task in Python, whether you are processing log entries, implementing undo functionality, or simply displaying data from newest to oldest. Python provides several approaches to iterate backward through a list, each with different trade-offs in memory usage, performance, and readability.
Using range() with a Negative Step
The range() function accepts three arguments: start, stop, and step. By setting the step to -1, you iterate from the last index down to zero. This approach works directly with indices and does not create a copy of the list.
Breaking down the arguments:
len(my_list) - 1is the index of the last element (4 in this case).- The second
-1means the range stops before reaching -1, so it includes index 0. - The third
-1is the step, moving backward one position at a time.
This method is memory-efficient because range() produces indices lazily without allocating a new list. It is a good choice when you need the index value during iteration, for example to modify elements in place.
Using reversed()
The built-in reversed() function returns a reverse iterator over the original list. It does not create a copy of the data, making it both memory-efficient and readable.
Under the hood, reversed() calls the __reversed__() method on the list object, which yields elements from the last index to the first. Since it returns an iterator, it consumes O(1) extra memory regardless of list size.
If you need a reversed list object rather than just iterating, you can wrap it in list():
Using Slice Notation [::-1]
Python slice notation supports a step parameter. Using [::-1] creates a new list with elements in reverse order.
This approach is concise and idiomatic. However, it creates a full copy of the list in memory, which matters for large datasets. For a list with one million elements, [::-1] allocates a second list of one million references.
You can also assign the reversed slice to a variable for later use:
Using a While Loop
A manual while loop gives you full control over the iteration process. This can be useful when you need custom skip logic or early termination.
While this is the most verbose approach, it allows you to adjust the step size, skip certain indices, or break out of the loop based on conditions that are harder to express with range() or reversed().
Performance Comparison
Each method has different characteristics when applied to large lists:
In typical benchmarks, [::-1] is the fastest because it runs at C level internally, but it uses the most memory. reversed() strikes a balance between speed and memory, while range() with indexing is slightly slower due to repeated __getitem__ calls.
Common Pitfalls
- Off-by-one errors in range(): Forgetting that
range()excludes the stop value leads to skipping the first element. The stop must be-1, not0. - Mutating during iteration: Modifying a list while iterating over it with
reversed()or slicing can produce unexpected results or errors. - Memory overhead with slicing: Using
[::-1]on very large lists doubles memory consumption because it creates a full copy. - Confusing reversed() with .reverse(): The
reversed()function returns a new iterator and leaves the original list unchanged, whilelist.reverse()modifies the list in place and returnsNone. - Using range() when you do not need the index: If you only need the element values,
reversed()is cleaner and avoids index bookkeeping.
Summary
- Use
range(len(lst) - 1, -1, -1)when you need both the index and the value during reverse iteration. - Use
reversed()for a memory-efficient, readable reverse iterator that does not copy the list. - Use
[::-1]for a concise one-liner that produces a new reversed list, accepting the memory cost. - Use a while loop when you need custom control flow such as variable step sizes or conditional breaks.
- For most applications,
reversed()is the recommended default because it combines low memory usage with clear intent.
Related reading
- Print binary tree in BFS fashion with O1 space
- Print current call stack from a method in code
- print directory tree
- Print list without brackets in a single row
- Print all properties of a Python Class
- Print in one line dynamically
- Print Specific nodes at a every level calculated by a given function
- Print two-dimensional array in spiral order

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.