Python for i in range in Reverse (Reverse a Range)

For a Python for i in range loop in reverse, either give range() a negative step, as in range(4, -1, -1), or wrap it in reversed(). Both count 4, 3, 2, 1, 0:

for i in range(4, -1, -1):
    print(i)

for i in reversed(range(5)):
    print(i)

Each loop here ran on Python 3.12.5, and the Command Prompt screenshots show the exact numbers printed.

I’ll show both ways, the off-by-one mistakes that produce empty or short ranges, looping backward with an index, safely deleting items, and why reversed(range()) uses almost no memory.

Two ways to reverse a range in Python

range(start, stop, step) with a negative step counts down from start to just above stop. reversed(range(n)) gives the same numbers and is usually easier to read:

for i in range(4, -1, -1):          # start, stop (excluded), step
    print(i, end=" ")
print()

for i in reversed(range(5)):        # same numbers, easier to read
    print(i, end=" ")
print()

print(list(range(10, 0, -2)))       # step back by 2
print(list(reversed(range(2, 11, 2))))

Output:

4 3 2 1 0 
4 3 2 1 0 
[10, 8, 6, 4, 2]
[10, 8, 6, 4, 2]
Command Prompt output of Python for loops counting down with range negative step, reversed(range), and a step of minus 2
Both loops print 4 to 0. A step of -2 skips every other number.

I reach for reversed(range(n)) when I want 0 to n – 1 backward, since there’s no -1 to get wrong. For forward loops, see for i in range in Python.

Why does my reverse range stop early or come out empty?

The stop value is always excluded, and the default step is +1. Those two rules cause nearly every reverse-range bug:

print(list(range(10, 0, -1)))       # stops at 1: 0 is the excluded stop
print(list(range(10, -1, -1)))      # include 0 by stopping at -1
print(list(range(0, 10, -1)))       # empty: can't count down from 0 to 10
print(list(range(10, 0)))           # empty: default step is +1

Output:

[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
[]
[]
Command Prompt output of Python reverse range off-by-one cases: stopping at 1, including 0 with stop -1, and two empty ranges
To include 0 when counting down, the stop must be -1. Forgetting the negative step gives an empty range.

An empty range doesn’t raise an error; the loop just doesn’t run. If a countdown silently does nothing, check the step first.

Looping backward with an index

Use range(len(items) - 1, -1, -1) for indexes, or reverse an enumerate() if you want index and value together. Slicing with [::-1] is simplest when you only need values:

cities = ["Austin", "Denver", "Boston", "Tampa"]

for i in range(len(cities) - 1, -1, -1):
    print(i, cities[i])

print("---")
for i, city in reversed(list(enumerate(cities))):     # reversed() needs a sequence
    print(i, city)

print("---")
for city in cities[::-1]:                              # just the values, no index
    print(city, end=" ")
print()

Output:

3 Tampa
2 Boston
1 Denver
0 Austin
---
3 Tampa
2 Boston
1 Denver
0 Austin
---
Tampa Boston Denver Austin
Command Prompt output of Python reverse loops over a list of US cities with range indexes, reversed enumerate and slicing
All three walk the list from Tampa back to Austin.

reversed() can’t take an enumerate object directly, which is why it’s wrapped in list(). More in what enumerate does in Python and reversing a list in Python.

Deleting items while looping: go backward

Removing items while looping forward shifts the rest of the list left, so you skip elements. Looping from the end avoids that, because earlier indexes never move:

prices = [19.99, 0.00, 4.50, 0.00, 12.00, 0.00]

# deleting while looping forward skips items; looping backward is safe
for i in range(len(prices) - 1, -1, -1):
    if prices[i] == 0.00:
        del prices[i]
print(prices)

Output:

[19.99, 4.5, 12.0]

A list comprehension like [p for p in prices if p != 0] is usually cleaner still. See Python list comprehension for that approach.

A countdown with a reverse range

A countdown is the classic use. range(5, 0, -1) gives 5 down to 1, and time.sleep() paces it:

import time

for seconds_left in range(5, 0, -1):
    print(f"Launch in {seconds_left}...")
    time.sleep(0.2)
print("Liftoff!")

Output:

Launch in 5...
Launch in 4...
Launch in 3...
Launch in 2...
Launch in 1...
Liftoff!

Is reversed(range()) memory efficient?

Yes. reversed(range(n)) and range(n)[::-1] don’t build a list; they compute each number when the loop asks for it. Turning the range into a list first costs memory for every number:

import sys

n = 10_000_000
print("reversed(range):", sys.getsizeof(reversed(range(n))), "bytes")    # lazy, tiny
print("range[::-1]:    ", sys.getsizeof(range(n)[::-1]), "bytes")         # still a range object
print("list reversed:  ", sys.getsizeof(list(range(n))[::-1]), "bytes")   # builds every number
print(range(n)[::-1])

Output:

reversed(range): 32 bytes
range[::-1]:     48 bytes
list reversed:   80000056 bytes
range(9999999, -1, -1)
Command Prompt output comparing memory of reversed(range), a reversed range slice and a reversed list of ten million numbers
A few dozen bytes for the lazy versions versus about 80 MB for the list.

Slicing a range even returns another range, as the last line shows, so you can store it and reuse it freely.

Reverse range cheat sheet

You wantWrite
n – 1 down to 0reversed(range(n)) or range(n - 1, -1, -1)
10 down to 1range(10, 0, -1)
10 down to 0range(10, -1, -1)
Every other, downwardrange(10, 0, -2)
List indexes backwardrange(len(a) - 1, -1, -1)
Values backwardreversed(a) or a[::-1]

More loop guides worth bookmarking:

Frequently asked questions

How do I write for i in range in reverse in Python?

Use for i in range(n - 1, -1, -1): or for i in reversed(range(n)):. Both count from n – 1 down to 0.

Why doesn’t range(10, 0) count backward?

The default step is +1. Add a negative step: range(10, 0, -1).

How do I include 0 in a reverse range?

Set the stop to -1, since the stop value is excluded: range(10, -1, -1).

Is reversed(range(n)) slower than a negative step?

No. Both are lazy and run at about the same speed. Pick whichever reads better.

How do I loop over a list backward with indexes?

Use range(len(items) - 1, -1, -1), or reversed(list(enumerate(items))) for index and value pairs.

Where is range documented?

See range in the Python docs.