Skip to content
TaeyoungKim.dev

Why Python range() Excludes the Stop Value: Numbering Items Correctly

PythonWritten 2 min readTaeyoungKim
LinkedInX

You number three files starting at 1, but the last file disappears from the output. The loop finishes without an error, and the first two lines look fine. The second argument to range() is the boundary where iteration stops, not the final value it produces.

Why doesn't range(1, 4) produce 4?

range(start, stop) begins at start and ends before stop.

python
print(list(range(1, 4)))  # [1, 2, 3]
print(list(range(4)))     # [0, 1, 2, 3]

The stop value is excluded. To include 4 when starting at 1, use range(1, 5). With one argument, as in range(4), the default start is 0.

The diagram marks 4 as the exclusive stop boundary. range(4) uses the same boundary but starts at 0.

The missing file when numbering a list

Consider a three-file list. len(files) is 3, but this loop does not include its stop value of 3:

python
files = ["app.log", "db.log", "web.log"]

for number in range(1, len(files)):
    print(number, files[number - 1])
text
1 app.log
2 db.log

web.log is still in the list. The loop simply produces only [1, 2]. To number all three files, add 1 to the exclusive stop boundary:

python
for number in range(1, len(files) + 1):
    print(number, files[number - 1])
text
1 app.log
2 db.log
3 web.log

The number - 1 matters too. Display numbers start at 1, while list indexes start at 0. Using files[number] would skip the first file and eventually raise IndexError.

Is enumerate() simpler for display numbers?

If you only want to number each file starting at 1, avoid manual index arithmetic:

python
for number, filename in enumerate(files, start=1):
    print(number, filename)

The output matches the corrected loop. enumerate() gives you a display number and the corresponding item, so there is no len(files) + 1 or number - 1 to coordinate. If you need the index itself, range(len(files)) produces 0, 1, 2, which you can use directly as files[index].

Also check the boundary cases: an empty list and a one-item list.

python
for count in (0, 1, 3):
    numbers = list(range(1, count + 1))
    assert len(numbers) == count

This checks that the loop produces the intended number of values. If the contents matter, also verify that the final item was processed.

Key takeaways

range(start, stop) excludes stop. Use range(1, N + 1) for numbers from 1 through N, or range(N) for zero-based list indexes. To attach display numbers to items, enumerate(items, start=1) is usually clearer and leaves less room for an off-by-one error.

Author

TaeyoungKim

Connecting technical foundations with implementation, verification, and production decisions.

#Python#range#for loop#enumerate#list index

Read next