What you'll learn
- Loop over every item in a string or list with
for - Generate number sequences with
range()and its start, stop, and step - Number items as you go with
enumerate() - Nest one loop inside another and know what that costs
Concept
A for loop visits each item in a collection, one at a time, and runs the block once per item. You name the item on the first line: for letter in word: means "for each character in the string, call it letter and run the block". There is no counter to set up, test, or increment; Python handles all of that. When you know what you want to loop over, for is almost always the right loop.

When you want to loop a number of times rather than over a collection, range() produces the numbers for you. range(5) gives 0, 1, 2, 3, 4: five numbers, starting at zero, stopping before five. range(2, 8) starts at 2. range(0, 20, 5) steps by 5. The stop value is never included, which matches the way slicing works and means range(len(items)) is exactly the valid indexes of items.
| Call | Produces | Rule |
|---|---|---|
range(5) |
0 1 2 3 4 | stop only: starts at 0 |
range(2, 8) |
2 3 4 5 6 7 | start and stop |
range(0, 20, 5) |
0 5 10 15 | start, stop, step |
range(10, 0, -3) |
10 7 4 1 | negative step counts down |
Often you want both the item and its position. enumerate(items) gives you pairs of position and item, so for i, name in enumerate(names): reads naturally and avoids indexing by hand. Pass start=1 when the numbering is for people, who count from one.
A loop inside a loop runs the inner block once for every combination. Two loops of ten items each mean a hundred runs of the inner block; that is fine for a hundred, and a problem for a million. Nested loops are the right tool for grids, tables, and pairs, and they are the first thing to look at when a program is slow.

Code
Looping over a string and over a list. Each item is named, used, and forgotten; the loop variable takes the next value on every round.
# items.py
for letter in "abc":
print(letter, end=" ")
print()
colors = ["red", "green", "blue"]
for color in colors:
print(color.upper())
a b c
RED
GREEN
BLUEEvery form of range. Wrapping in list() shows the numbers a range would produce, which is a handy way to check a range before you loop over it.
# ranges.py
print(list(range(5)))
print(list(range(2, 8)))
print(list(range(0, 20, 5)))
print(list(range(10, 0, -3)))
total = 0
for n in range(1, 101):
total += n
print("1 to 100 sums to", total)
[0, 1, 2, 3, 4]
[2, 3, 4, 5, 6, 7]
[0, 5, 10, 15]
[10, 7, 4, 1]
1 to 100 sums to 5050enumerate gives position and item together, and start=1 numbers them for a human reader.
# numbered.py
steps = ["install Python", "open VS Code", "run hello.py"]
for i, step in enumerate(steps, start=1):
print(f"{i}. {step}")
1. install Python
2. open VS Code
3. run hello.pyA nested loop building a small multiplication grid. The inner loop prints one row with end keeping the numbers on a line; the outer loop's print() ends the row.
# grid.py
for row in range(1, 4):
for col in range(1, 4):
print(f"{row * col:3}", end="")
print()
1 2 3
2 4 6
3 6 9Try it yourself
Create stars.py. Use a for loop over range(1, 6) to print a triangle of stars: one star on the first line, two on the second, up to five. Then print the same triangle upside down with a range that counts down. Finally, use enumerate over a list of three of your favorite tools to print a numbered list starting at 1.
Common mistakes
- Expecting
range(5)to include 5. It stops before the stop value;range(1, 6)gives 1 to 5. - Looping over indexes when you want items.
for i in range(len(colors)): print(colors[i])works butfor color in colors:says what you mean; useenumeratewhen you need both. - Changing a list while looping over it. Adding or removing items inside
for item in items:confuses the loop; build a new list instead, which you will learn to do with comprehensions.
What's next
forvisits each item of a collection and names it for you; no counter needed.range(start, stop, step)produces numbers up to but not including stop;enumerate(items, start=1)gives positions with items.- Nested loops run the inner block once per combination, which is powerful and the first place to look when code is slow.
You have both kinds of loop. Next you will learn the handful of shapes that loops take in almost every program, so you recognize them on sight and write them without thinking.