Learning LibraryCore Coding LibraryTeens

range() in Python: start, stop, and step

range() is a lazy number generator. Its three arguments — start, stop, step — let you lay out anything on a grid, like a wave at perfectly even x-positions.

The big idea

range(start, stop, step) yields numbers from start, increasing by step, up to but not including stop.

See it in code

1The basics

Start by seeing what range yields. Wrap it in list(...) to force the values out: one argument counts from 0, two arguments set a start and a stop:

python
print("range(4):", list(range(4)))
print("range(2, 6):", list(range(2, 6)))
Run it — stop is always exclusive:
range(4): [0, 1, 2, 3]
range(2, 6): [2, 3, 4, 5]

range(4) is 0…3; range(2, 6) is 2…5. In both, the stop value itself never appears — that exclusive stop is the rule that trips everyone up.

2A step further

The third argument, step, sets the gap between values — which is exactly what controls even spacing. Same start, different step, different spread:

python
print("step 40:", list(range(0, 200, 40)))
print("step 88:", list(range(0, 400, 88)))
Run it — step decides how far apart the values land:
step 40: [0, 40, 80, 120, 160]
step 88: [0, 88, 176, 264, 352]

Bump the step from 40 to 88 and the values spread out. That's the knob we're about to use to space enemies evenly across the screen.

3In our world

Now let range produce the positions directly. range(40, 480, 88) starts at 40, jumps by 88 each pass, and stops before 480 — and each value it yields is an x-position for an enemy:

python
from game import Stage, Enemy

screen = Stage.create()
Stage.clear(screen)

print("x positions:", list(range(40, 480, 88)))

for x in range(40, 480, 88):
    Enemy(x, 90).draw(screen)
Run it — range produces the x-positions, one enemy each:
x positions: [40, 128, 216, 304, 392]
Five purple enemy sprites evenly spaced across the top of a dark play area.

Five positions, evenly spaced, and 480 itself never appears — stop is exclusive, just like the warm-ups. The next value would have been 480, off the right edge anyway. That exclusive-stop rule is exactly what makes range line up with pixel widths.

The same idea, everywhere

The three-arg form is a workhorse: range(0, 100, 10) for tick marks, range(len(prices)) to index a series, range(10, 0, -1) to count down. It never builds the full list in memory — it produces values on demand, so range(1_000_000) costs almost nothing until you loop it.

Try it yourself

Change the step to 74 and the spacing tightens. Then count backward with range(5, 0, -1) and print it — a negative step reverses direction. Wrap range in list(...) any time you want to see the values.

The common mistake

Off-by-one from the exclusive stop. range(1, 6) is 1, 2, 3, 4, 5 — five numbers, and 6 is not included. When you want positions 0 through n, you need range(n + 1).

What it unlocks

Precise counting drives for loops, grids via nested loops, and one-line builders with list comprehensions.

Want the simpler version? Read the Kids version →