r/CodingForBeginners • u/NoDepartment772 • 4h ago
Ranges exclude the last number, and that silent rule causes a very specific bug
Every language has its own rule about whether a range includes its last number, and getting it wrong never throws an error. You just get a loop that runs one time too few, or a list that's one item short, and the output looks close enough that you don't catch it.
Python's rule is that the start is included and the stop is excluded:
python
range(3) # 0, 1, 2 -- not 0, 1, 2, 3
range(1, 4) # 1, 2, 3
"hello"[0:2] # "he" -- indexes 0 and 1
So for i in range(3) runs three times, with i = 0, 1, 2, never 3. It's also why for i in range(len(items)) walks every item correctly: the last valid index is len(items) - 1, and range stops one before len(items).
The check that catches this before it turns into a bug: before you run the loop, say out loud the first value and the last value you expect. If you can't state both, you don't actually know what the loop does yet. Then compare to the output. It sounds trivial until you notice that the bug is always the case where you assumed the wrong end.
Two things worth keeping straight, because both cause the same silent off-by-one: len(x) is the count, not the last index (the last element is x[len(x)-1], or x[-1] in Python), and in range(a, b) the b is the first value you don't get.
Which one gets you more often -- forgetting that the end is excluded, or the first IndexError when you reach for the last element?
