The range() Function
Before the for loop, this. A for loop needs something to count through, and range() is what produces it — a run of numbers, described by where to start, where to stop, and how big a step to take. Meet it now and the loop header will hold no surprises.
1What range() does
range() is a built-in function, like print(), len() and int(). Give it a start, a stop and a step, and it produces the whole run of numbers in between:
range(start, stop, step)
| | |
| | +-- the jump from one number to the next
| +-------- where to stop: NOT included
+--------------- where to start: includedTo see the numbers, wrap the call in list() — the same list() that turned a string into a list of characters:
print(list(range(1, 6, 1)))[1, 2, 3, 4, 5]
range() is not a list. Print it on its own and you get range(1, 6) back, not the numbers — because it does not build them all at once, it hands them over one at a time as they are needed. That is exactly what a loop wants, and it is why range(1, 1000000) costs no memory worth mentioning. Use list() when you want to look at them.print(range(1, 6))
print(list(range(1, 6)))range(1, 6) [1, 2, 3, 4, 5]
2The rule that costs marks: stop is excluded
range(1, 6) gives you 1, 2, 3, 4, 5. The 6 is where the counting stops, and it does not appear. Start is included; stop is not.
So to count from 1 to 10 you write range(1, 11). This looks wrong the first fifty times and is correct every time.
range(1, 6) gives 6 − 1 = 5 numbers. range(1, 11) gives 10. That subtraction is the quickest way to check a loop header in an exam.3Build one and watch
Move the three numbers below. The value struck through in red is stop — drawn on the line, so you can see the one that never joins in.
Move the three numbers and watch which values come out — and which one never does.
list(range(1, 6, 1))Green values are the ones the loop would count through. stop is struck through because it is never included — it is where counting stops, not the last value.
4The step: counting in jumps
The third number is how far to jump each time. Make it 2 and you get every second number:
print(list(range(2, 11, 2)))
print(list(range(3, 17, 4)))[2, 4, 6, 8, 10] [3, 7, 11, 15]
range(1, 6) — and Python fills the step in as 1, so it counts one at a time. There is no other value it could quietly take, and no way for a range to have no step at all. You met the same rule with slicing, where a missing step is also 1: it is one rule in two places, not two rules.# these two lines mean exactly the same thing
print(list(range(1, 6)))
print(list(range(1, 6, 1)))[1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
A negative step counts backwards. Then start must be the bigger number, because the counting has to move towards stop:
print(list(range(13, 3, -3)))[13, 10, 7, 4]
Note where it ends. The next number after 4 would be 1, which is past the stop of 3, so the run finishes at 4 — the same rule as before, just travelling the other way.
5Leaving numbers out — and what Python fills in
You may give range() three numbers, two, or one. The ones you leave out are filled in for you, and this is where a student who has only ever seen the three-number form starts guessing:
| You write | Python reads it as | You get |
|---|---|---|
range(1, 6, 1) | range(1, 6, 1) | [1, 2, 3, 4, 5] |
range(1, 6) | range(1, 6, 1) | [1, 2, 3, 4, 5] |
range(5) | range(0, 5, 1) | [0, 1, 2, 3, 4] |
The single-number form is the one that surprises people: range(5) is a stop, not a start. It counts from 0, and it gives you five numbers — but they are 0 to 4, not 1 to 5.
print(list(range(5)))
print(list(range(1, 6)))[0, 1, 2, 3, 4] [1, 2, 3, 4, 5]
6When range() gives you nothing at all
Ask it to count from 6 up to 2, and it does not count backwards to be helpful. It produces no numbers whatsoever:
print(list(range(6, 2)))[]
This matters more than it looks. Put that in a for loop and the body never runs — not once. There is no error, no warning and no output, so a program that silently does nothing is very often a range() whose start and stop are the wrong way round.
range() refuses outright. A step of 0 gives ValueError: range() arg 3 must not be zero — with no jump it could never get anywhere. And a decimal gives TypeError: 'float' object cannot be interpreted as an integer: range() counts in whole numbers only, so range(1, 6.5) is refused.7Try it
Predict each line before you run it. The last one is the trap from the section above.
8Recap
range(start, stop, step) produces a run of whole numbers. start is included, stop is excluded, and step is the jump — negative to count backwards. Leave out the step and it is 1; leave out the start as well and it is 0, so range(5) means 0, 1, 2, 3, 4. It is not a list: use list() to see the numbers.What does list(range(1, 5)) give?
Which range would a loop use to count 1 to 10?
How many numbers does range(5) produce, and what is the first one?