Hand the repetition to the machine
To print the numbers 1 through 100, you are not going to write 100 lines of print. A loop is the mechanism for saying something once and having it happen many times. It's the first moment where a computer starts doing work that would be unreasonable by hand.
for i in range(5):
print(i)
Output:
0
1
2
3
4
Read it as: "for each number that range(5) produces, call it i, and run the indented block." The block runs five times, and i holds a different value each time.
Note the colon and the four-space indent. Same grammar as if.
What range actually gives you
print(list(range(5)))
print(list(range(1, 6)))
print(list(range(0, 10, 2)))
Output:
[0, 1, 2, 3, 4]
[1, 2, 3, 4, 5]
[0, 2, 4, 6, 8]
(list(...) is here only so you can see the contents printed on one line. In a real loop you'd write for i in range(5): directly.)
- One argument: start at 0, stop before that number.
- Two arguments: start at the first, stop before the second.
- Three arguments: the third is the step size.
The end number is never included. Beginners lose real time to this. range(1, 5) gives you four numbers, not five. The industry name for getting this wrong is an off-by-one error, and it's common enough to have its own name for a reason.
Why is it designed this way? Because range(n) then gives you exactly n items, and range(0, 10) followed by range(10, 20) covers 0 through 19 with no gap and no overlap. Once you're used to it, it causes fewer bugs than the alternative.
Habit worth building: after writing a loop, say out loud what the first value and the last value will be. Ten seconds there saves ten minutes of debugging.
for is really about going through a collection
Counting is a side effect. What for actually does is take items out of a group, one at a time:
for fruit in ["apple", "banana", "orange"]:
print(f"I ate an {fruit}")
Output:
I ate an apple
I ate an banana
I ate an orange
(The grammar is off for two of them. Fixing that would take an if, and it's a decent exercise once you finish this lesson.)
Strings work too, because a string is a sequence of characters:
for ch in "abc":
print(ch)
Output:
a
b
c
i, fruit, ch are names you invent for "the current one." Python doesn't care what you call it. Your reader does — pick something meaningful.
while: when you don't know how many times
for is for a known number of rounds. while is for "keep going as long as this stays true":
count = 0
while count < 3:
print(count)
count += 1
print("done")
Output:
0
1
2
done
Each round, Python checks the condition first. When count reaches 3, count < 3 is False and the loop ends.
The danger with while is the infinite loop. Delete the count += 1 line and nothing ever changes the condition, so the program prints 0 forever until you kill it. Build this habit now: after writing a while, ask yourself "what, specifically, will make this stop?" If you can't point to the line, you have a bug.
A realistic use:
password = ""
while password != "opensesame":
password = input("Password: ")
print("Welcome in")
The loop keeps asking until the typed value matches. What makes it stop is clear — the input line can change password.
break and continue
for i in range(10):
if i == 3:
break
print(i)
Output:
0
1
2
break abandons the entire loop immediately.
for i in range(5):
if i % 2 == 0:
continue
print(i)
Output:
1
3
continue skips the rest of this round only, and starts the next one. Since i % 2 == 0 is True for 0, 2, and 4, those rounds skip the print.
Short version: break means "I'm done with this whole thing," continue means "skip this one."
The accumulator: the pattern you'll use most
total = 0
for i in range(1, 101):
total += i
print(total)
Output:
5050
The shape here is worth memorizing because it shows up everywhere:
- Before the loop, set up an empty container —
total = 0, orcount = 0, orresults = []. - Inside the loop, add to it once per round.
- After the loop, use it.
Summing, counting, filtering, finding the largest — all of them are this same three-step shape with a different middle. The most common mistake is putting step 1 inside the loop by accident, which resets it every round and leaves you with only the last value.
Ten-second check
for i in range(1, 4):
print(i * 2)
The answer is three lines: 2, 4, 6. range(1, 4) produces 1, 2, and 3 — the 4 marks where to stop, and is never handed to the loop.