Fundamentals · Lesson 11 of 94

for loops and range

Watch this lesson

View full playlist ↗

Read the lesson

What you'll learn

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.

for loops and range: 'abc' → letter = 'a' → letter = 'b' → letter = 'c' → done
for loops and range · Figure 1 · Open for full size

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.

for loops and range: for row in 1..3 → for col in 1..3 → print(row * col) → 9 prints
for loops and range · Figure 2 · Open for full size

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())
Output
a b c 
RED
GREEN
BLUE

Every 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)
Output
[0, 1, 2, 3, 4]
[2, 3, 4, 5, 6, 7]
[0, 5, 10, 15]
[10, 7, 4, 1]
1 to 100 sums to 5050

enumerate 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}")
Output
1. install Python
2. open VS Code
3. run hello.py

A 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()
Output
  1  2  3
  2  4  6
  3  6  9

Try 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

What's next

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.

Course overview