Loops let you repeat work without copy-pasting code. Python has two: for, which repeats a fixed number of times (or once per item in a collection), and while, which repeats as long as a condition stays true.
range(n) produces the numbers 0, 1, 2, ..., n-1 — n numbers total, starting at 0:
for i in range(5):
print(i)
# 0 1 2 3 4
range(start, stop) starts somewhere other than 0, and still stops before stop:
for i in range(1, 6):
print(i)
# 1 2 3 4 5
That "stops before, not at, stop" behavior trips up a lot of beginners — if you want to include n itself, you need range(1, n + 1).
range(start, stop, step) adds a step size:
for i in range(0, 10, 2):
print(i)
# 0 2 4 6 8
You can loop over a string, list, or other collection directly, without range() at all:
for char in "abc":
print(char)
# a b c
for word in ["the", "quick", "fox"]:
print(word)
# the quick fox
This is almost always preferable to indexing with range(len(...)) when you don't actually need the index.
The single most common loop pattern: start a variable at some initial value outside the loop, then update it on every iteration.
total = 0
for n in [1, 2, 3, 4]:
total += n # shorthand for total = total + n
# total is 10
You'll use this pattern — an accumulator that starts before the loop and updates inside it — constantly for the rest of this section.