for loops
A loop runs the same lines again and again, once for each item. Instead of writing print five times for five lamps, you write it once and let the loop repeat it. This lesson is the best place to use Step: you can watch the loop go around and the loop variable change each time.
1lamps = ["Mill Road", "Bridge", "Market"]2for lamp in lamps:3 print("Lighting", lamp)4print("All lit")
Lighting Mill Road Lighting Bridge Lighting Market All lit
How a for loop works
| Piece | What it does |
|---|---|
for lamp in lamps: | Take the items of lamps one by one. Each time around, lamp holds the current item. The line ends with a colon. |
| the indented lines | The body: they run once for every item. |
| the first line that is not indented | It is after the loop, so it runs once, when the loop is done. |
You choose the name of the loop variable. Pick one that says what a single item is: for lamp in lamps, for house in houses.
How many times is done printed?
1for n in [1, 2, 3]:2 print(n)3print("done")
print("done") is not indented, so it is not part of the loop. It runs once, after the loop has printed 1, 2 and 3.
Looping over a string
A string is a sequence of characters, so a for loop can walk through it one character at a time.
1for letter in "ore":2 print(letter, letter.upper())
o O r R e E
Counting with range()
To repeat something a number of times, loop over range(). It produces numbers on demand. Wrap it in list() to see them all at once:
1print(list(range(5)))2print(list(range(2, 6)))3print(list(range(0, 20, 5)))4print(list(range(5, 0, -1)))
[0, 1, 2, 3, 4] [2, 3, 4, 5] [0, 5, 10, 15] [5, 4, 3, 2, 1]
| Form | Counts | Example |
|---|---|---|
range(stop) | from 0 up to, but not including, stop | range(5) is 0 to 4 |
range(start, stop) | from start up to, not including, stop | range(2, 6) is 2 to 5 |
range(start, stop, step) | in jumps of step; a negative step counts down | range(5, 0, -1) is 5 to 1 |
The end number is never included. range(5) gives exactly 5 numbers, which is why it is the usual way to say "do this 5 times":
1for night in range(3):2 print("Night", night + 1, "- lamps on")
Night 1 - lamps on Night 2 - lamps on Night 3 - lamps on
What does this print?
1for i in range(5, 2):2 print(i)3print("end")
range(5, 2) counts up from 5 and stops before 2, so it is empty and the body never runs. To count down, give a negative step: range(5, 2, -1).
Adding up as you go
A common pattern: make a variable before the loop, update it inside, use it after. An if inside the loop lets you act only on some items.
1loads = [3, 8, 2, 6]2total = 03big = 04for ore in loads:5 total += ore6 if ore >= 5:7 big += 18print("Total ore:", total)9print("Big loads:", big)
Total ore: 19 Big loads: 2
Tip: Press Step here and watch total and big change each time around. If total = 0 were inside the loop, it would be reset every time.
Numbering with enumerate()
Sometimes you need the position as well as the item. enumerate() gives you both, as a pair you unpack into two names, just like tuple unpacking. It counts from 0 unless you give start.
1houses = ["bakery", "forge", "mill"]2for i, house in enumerate(houses):3 print(i, house)4for number, house in enumerate(houses, start=1):5 print(f"{number}. {house}")
0 bakery 1 forge 2 mill 1. bakery 2. forge 3. mill
Two lists side by side with zip()
zip() walks through two lists together. Each time around you get one item from each. If the lists differ in length, it stops at the end of the shorter one.
1miners = ["Ada", "Ben", "Cleo"]2amounts = [12, 7, 9]3for name, amount in zip(miners, amounts):4 print(f"{name} mined {amount} ore")
Ada mined 12 ore Ben mined 7 ore Cleo mined 9 ore
Looping over a dictionary
A loop over a dictionary gives you its keys. Loop over .items() to get each key with its value.
1stock = {"iron": 14, "copper": 6, "gold": 2}2for item in stock:3 print(item)4for item, count in stock.items():5 print(f"{item}: {count}")
iron copper gold iron: 14 copper: 6 gold: 2
Use .values() when you only need the values. The items come out in the order they were added.
break and continue
break leaves the loop at once; nothing more of it runs. Here the loop stops at the first empty cart, and the 5 and the 9 are never unloaded:
1loads = [4, 7, 0, 5, 9]2for ore in loads:3 if ore == 0:4 print("Empty cart, stop")5 break6 print("Unload", ore)
Unload 4 Unload 7 Empty cart, stop
continue skips the rest of the body for this item and goes on with the next one:
1lamps = ["on", "off", "on", "off"]2for i, state in enumerate(lamps):3 if state == "on":4 continue5 print("Light lamp", i)
Light lamp 1 Light lamp 3
| Keyword | What happens |
|---|---|
break | Leave the loop now. The program goes on after the loop. |
continue | Skip to the next item. The loop goes on. |
Practice
Write the code, then press Check. A hint costs nothing; the answer is there when you need it. Use Step if the output is not what you expect.
Countdown
✓Change the range() so the program counts down 3, 2, 1, then prints Go!.
3 2 1 Go!
1for n in range(3):2 print(n)3print("Go!")
One to a hundred
✓Use a loop to add up all the whole numbers from 1 to 100, then print the total.
5050
1total = 02# Your loop here3print(total)
Running low
✓Print only the items that have fewer than 5 left, as item: count.
copper: 3 gold: 0
1stock = {"iron": 14, "copper": 3, "coal": 22, "gold": 0}2for item in stock:3 print(item)
What you learned
for x in something:runs the indented body once for each item of a list, string or dictionary.range(stop),range(start, stop)andrange(start, stop, step)count; the stop is never included, and a range can be empty.- Set a variable before the loop and update it inside to add up or count; use
ifto pick items. enumerate()gives the position with each item;zip()walks two lists together;.items()gives keys with values.breakleaves the loop;continueskips to the next item.