Chapter 4

Repeating Work

Printing ten lines by hand would mean ten print() calls. A loop does it in a few lines, however many times you need. This chapter covers for, the loop you'll reach for most, and while, the one you'll reach for when you don't know the count in advance.

for, over values you already have

for runs a block once for each value in a group, in order:

amounts = [4.50, 12.00, 32.10]

for amount in amounts:
    print(amount)
Output
4.5
12.0
32.1

amount is a new variable, created by the loop, holding the current value on each pass. amounts is a list, Chapter 5's whole subject; for now, just read it as an ordered group of values in square brackets, separated by commas.

You'll use this shape constantly: loop over a group, do something with each value. Adding them up is the most common version:

amounts = [4.50, 12.00, 32.10]
total = 0

for amount in amounts:
    total = total + amount

print(total)
Output
48.6

total = total + amount reassigns total to its old value plus the current one, a running total. This pattern, starting a variable before the loop and updating it each pass, comes up so often that Python has a shorthand for it:

amounts = [4.50, 12.00, 32.10]
total = 0

for amount in amounts:
    total += amount

print(total)
Output
48.6

total += amount means exactly total = total + amount. -=, *=, and /= work the same way for their operators.

range()

range() produces a sequence of numbers to loop over, useful when you want to repeat something a specific number of times rather than loop over values you already have:

for i in range(5):
    print(i)
Output
0
1
2
3
4

range(5) counts from 0 up to, but not including, 5, which is why you get five numbers, 0 through 4. range() takes up to three arguments: a start, a stop, and a step.

for i in range(1, 6):
    print(i)
Output
1
2
3
4
5
for i in range(0, 10, 2):
    print(i)
Output
0
2
4
6
8

range(1, 6) starts at 1 and stops before 6. range(0, 10, 2) starts at 0, stops before 10, and counts by 2s. i is a conventional name for a loop counter; you'll see it constantly in other people's code, and it's fine to use it when the loop genuinely is just counting, the way it is here.

while

while repeats a block for as long as its condition stays True, checked before each pass:

total = 0
amounts = [4.50, 12.00, 32.10, 8.75, 45.00]
budget = 20
i = 0

while total < budget and i < len(amounts):
    total += amounts[i]
    i += 1

print(f"stopped at {total}, after {i} entries")
Output
stopped at 48.6, after 3 entries

This is the shape you reach for when you don't know in advance how many times you'll loop, here: "keep adding entries until the running total passes the budget." amounts[i] picks out one value by position; that's indexing, which Chapter 5 covers properly.

The single most common while mistake is forgetting to change something the condition depends on, which loops forever:

total = 0
budget = 20

while total < budget:
    print("still under budget")
    # total never changes, so this never stops

That prints "still under budget" forever, because total never moves toward the condition becoming false. If a script you run seems to hang, check every while loop for exactly this: does something inside the loop change the value the condition depends on? Ctrl-C in your terminal stops a runaway script.

break and continue

break exits a loop immediately, for or while, skipping whatever's left:

amounts = [4.50, 12.00, 32.10, 8.75]

for amount in amounts:
    if amount > 20:
        print(f"found one over 20: {amount}")
        break
Output
found one over 20: 32.1

Without break, the loop would keep checking every remaining amount even after finding what it was looking for.

continue skips the rest of the current pass and moves to the next one, without leaving the loop entirely:

amounts = [4.50, 12.00, 32.10, 8.75]

for amount in amounts:
    if amount < 10:
        continue
    print(amount)
Output
12.0
32.1

Amounts under 10 are skipped; everything else prints.

A loop inside a loop

A loop's block can contain anything, including another loop. Here's a list of shopping trips, each one itself a list of amounts:

trips = [[4.50, 12.00], [32.10, 8.75, 45.00]]
grand_total = 0

for trip in trips:
    trip_total = 0
    for amount in trip:
        trip_total += amount
    print(f"trip: {trip_total}")
    grand_total += trip_total

print(f"grand total: {grand_total}")
Output
trip: 16.5
trip: 85.85
grand total: 102.35

The outer for picks one trip at a time; the inner for, fully indented inside the outer one's block, adds up that single trip's amounts before the outer loop moves on to the next. trip_total resets to 0 at the start of every pass through the outer loop, which is exactly why each trip's total comes out right instead of accumulating across trips. Watch your indentation carefully here: the inner loop's body is indented twice, once for the outer for and once more for the inner one.

Practice

Try each of these before you read the solution under it.

  1. Given amounts = [4.50, 12.00, 32.10, 8.75, 45.00], print each one that's greater than 10, using for.
  2. Print every third number from 0 up to and including 30, using range() with a step.
  3. Using while, count how many amounts from amounts = [4.50, 12.00, 32.10, 8.75, 45.00] it takes, added in order, to reach or pass a total of 50.
  4. Given trips = [[6.00, 3.50], [10.00, 4.25, 4.25]], print each trip's total on its own line, using a loop inside a loop.

Solutions

1.

amounts = [4.50, 12.00, 32.10, 8.75, 45.00]

for amount in amounts:
    if amount > 10:
        print(amount)
Output
12.0
32.1
45.0

2. range(0, 31, 3) needs 31, not 30, as the stop, since range never includes its stop value.

for n in range(0, 31, 3):
    print(n)
Output
0
3
6
9
12
15
18
21
24
27
30

3. A while loop with a counter and a running total, same shape as the budget example above.

amounts = [4.50, 12.00, 32.10, 8.75, 45.00]
total = 0
count = 0

while total < 50 and count < len(amounts):
    total += amounts[count]
    count += 1

print(f"{count} amounts, total {total}")
Output
4 amounts, total 57.35

4.

trips = [[6.00, 3.50], [10.00, 4.25, 4.25]]

for trip in trips:
    trip_total = 0
    for amount in trip:
        trip_total += amount
    print(trip_total)
Output
9.5
18.5

Where this leaves you

You can repeat work with for over a group of values or range() of numbers, use while when you don't know the count ahead of time, and you know what an infinite loop looks like and how to avoid one. You've also leaned on lists without formally meeting them yet. Chapter 5 makes the list itself the subject.