Loops
Problem
How much will you save?
You decide to save money: the first month you put aside €10, the second €20, the third €30, and so on, €10 more each time. How much will you have after 4 months?
total = 0total += 1 * 10total += 2 * 10total += 3 * 10total += 4 * 10print(total)100It works. But after 3 years that is 36 lines, almost all the same. And if the number of months is typed on the keyboard, you have no idea how many lines to write. You need a way to say "repeat this so many times".
The idea
for: repeat for each number
A piece of code that repeats is called a loop. The one you will use most is for. Here are the numbers from 1 to 10:
for i in range(1, 11): print(i)12345678910for i in range(1, 11): means "for each i among the numbers that range gives". i is the counter: on every round it gets the next number. range has three parts, separated by commas:
- Start:
1. The first number. If it is missing, as inrange(10), the start is 0. - Stop:
11. The stop is not included: the last number is 10. That is whyrange(1, 11)goes from 1 to 10. - Step: how much is added each time. If it is missing, it is 1.
range(3, 0, -1)counts down: 3, 2, 1.
The body is what is indented by 4 spaces after the colon, just like with if.
Each run of the body is called an iteration, or simply a round.
More precisely, if you are curious
- The step can be whatever you need: every other number, backward. And
range(10)counts from 0 to 9: still 10 rounds. Why you count from 0 will become clear in the lesson on lists.
for i in range(1, 11, 2): print(i, end=" ")print()for i in range(10, 0, -1): print(i, end=" ")print()for i in range(10): print(i, end=" ")print()1 3 5 7 910 9 8 7 6 5 4 3 2 10 1 2 3 4 5 6 7 8 9- In Python the counter is still there after the loop, with its last value. In Java, C# and JavaScript it is gone after the loop.
for i in range(1, 4): print(i)print("After the loop i is", i)123After the loop i is 3- Python has no
forwith a condition and a step likefor (int i = 1; i <= 10; i++)in Java. When you need "while something is true", there iswhile(coming up shortly).
See it
Round by round
These are the savings from the first card, with a loop. Watch how month and total change.
total = 0for month in range(1, 5): total += month * 10print(total) # 100Step by step, in words
- total starts at 0.
- month = 1, the first number from range(1, 5). We go into the body.
- Round 1: total += 1 * 10, total becomes 10.
- month becomes 2, the next number from range. One more round, total becomes 30.
- month 3: total becomes 60.
- month 4: total becomes 100.
- range(1, 5) has no more numbers: the stop value 5 is not included. The loop ends, and month stays 4.
- After the loop total is 100.
The body is one line, and it is written once. For 36 months you only change 5 to 37. You can even put a variable read from the keyboard there.
Try it
Countdown
What will the program print?
for sec in range(3, 0, -1): print(sec)print("Go!")range(3, 0, -1) counts down: 3, 2, 1. The stop value 0 is not included, so 0 is not printed. The line after the loop is not indented, so it runs at the end, once.The idea
while: until the end comes
Sometimes you don't know ahead of time how many rounds there will be. The cash register reads prices until the cashier enters 0, and then it gives the total. for does not fit here. while does: it repeats while the condition is true.
total = 0price = int(input())while price != 0: total += price price = int(input())print(f"Total: €{total}")12470Total: €23The first price is read before the loop, so the condition has something to check. The next one is read at the end of the body. If the first number is 0, the body does not run even once.
Sometimes the body has to run at least once, and the condition has to be checked after the round. For example, a question that repeats until the answer is acceptable. Java, C# and JavaScript have do-while for this. Python does not. You write while True:, a loop whose condition is always true, and inside it a break that stops it as soon as the answer is good (more on break shortly):
while True: print("How many tickets (1 to 10)?") count = int(input()) if 1 <= count <= 10: breakprint(f"Tickets booked: {count}")0153How many tickets (1 to 10)?How many tickets (1 to 10)?How many tickets (1 to 10)?Tickets booked: 3More precisely, if you are curious
- If the condition never becomes false, the loop never ends. This is an infinite loop: the program "hangs" and you have to stop it by hand. The most common cause is a forgotten change to the variable in the condition, for example a missing
price = …at the end of the body. -
while True:with nobreakinside is an infinite loop. Make sure there is a path tobreak. - Any for can be written as a while. You pick the one that reads more clearly:
forfor a known number of rounds,whilefor "until something happens".
Try it
Find the bug
The program should add up the numbers from 1 to 5: 1 + 2 + 3 + 4 + 5 = 15. It prints 10. Which line has the bug?
Pick the line with the bug.
The stop of range is not included: range(1, n) is 1, 2, 3, 4, and 5 is not added: 1 + 2 + 3 + 4 = 10. It needs range(1, n + 1).
A bug like this, with one round too many or too few, is the most common one with loops. A "dry run" catches it: write down i and total for every round on paper.
The sum is in total, not in sum: in Python sum is the name of a built-in function, and it is better not to take it.
The idea
break and continue
Two words change the usual flow of a loop.
continue skips the rest of the current round and moves on to the next one. You are listing appointment times from 9 to 17, but 13 is the lunch break:
for hour in range(9, 18): if hour == 13: continue print(f"{hour}:00")9:0010:0011:0012:0014:0015:0016:0017:00break stops the whole loop right away. You are looking for the first number that 91 divides by. Once you find it, there is no point in going on:
n = 91for d in range(2, n): if n % d == 0: print(f"{n} is divisible by {d}") break91 is divisible by 7More precisely, if you are curious
breakstops only the loop it is in. If it is in a nested loop (next card), the outer one keeps going.- You have already seen while True: with a break inside: a loop that ends not because of its condition, but because of a break in the right place.
The idea
A loop inside a loop
The movie theater has 3 rows of 4 seats. You want to print every seat. For each row you go through all the seats in it:
for row in range(1, 4): for seat in range(1, 5): print(f"[{row}-{seat}]", end="") print()[1-1][1-2][1-3][1-4][2-1][2-2][2-3][2-4][3-1][3-2][3-3][3-4]These are called nested loops. The inner loop goes all the way through on every round of the outer one: 3 rows · 4 seats = 12 prints. end="" tells print not to move to a new line, so the seats stay on one line. The empty print() after the inner loop moves to a new line.
Try it
Staircase
The first row should have one star, the second two, the fourth four. What goes in the blank?
for row in range(1, 5):
for star in range():
print("*", end="")
print()The inner loop has to run as many times as the number of the row. So its limit is row, the counter of the outer loop.
The idea
Random numbers for games
A dice game needs a number the program does not know ahead of time. random gives you one:
import random
dice = random.randint(1, 6)print(f"Rolled {dice}")random is a module: ready-made code that comes with Python. You bring it in with import random at the top of the file, just like math.
random.randint(1, 6) gives a whole number from 1 to 6. Careful: here both limits are included, unlike with range.
Each run gives a different number, so there is no output here. And here is a loop that rolls until it gets a six:
import random
rolls = 0while True: dice = random.randint(1, 6) rolls += 1 if dice == 6: breakprint(f"Six after {rolls} rolls")More precisely, if you are curious
- If you set a starting number with
random.seed(42), every run gives the same sequence. This helps with testing. random.random()gives a decimal number from 0 to 1 (not including 1), likeMath.random()in JavaScript.
- The numbers are not truly random: they are computed with a formula. They are good enough for games, but not for passwords and security.
Exercise
Loop exercises
Solve the exercises in your editor. Each one has sample input and output to compare yours with. You read the number the same way as in the lesson "Input and output".
1. Multiplication table. Read a number and print its products with the numbers from 1 to 10.
77 x 1 = 77 x 2 = 147 x 3 = 217 x 4 = 287 x 5 = 357 x 6 = 427 x 7 = 497 x 8 = 567 x 9 = 637 x 10 = 702. Prime number. A number is prime if it divides only by 1 and by itself: 2, 3, 5, 7, 11… Read a number and say whether it is prime. Hint: try the divisors from 2 up, and stop with break at the first one.
9191 is not primeFor 11 the output is "11 is prime".
3. The digits of a number. Read a positive whole number. Print it reversed and the sum of its digits. Hint: n % 10 is the last digit, and n // 10 drops the last digit. Repeat until the number becomes 0.
2024Reversed: 4202Sum of digits: 84. Guess the number. The computer "thinks of" a number from 1 to 100, and you look for it. After each guess the program says "It's lower." or "It's higher.", and at the end how many tries it took you. First write it with the secret number 37, so you can check it against the example:
502537It's lower.It's higher.You got it in 3 tries!Once it works, replace 37 with a random number from 1 to 100. Now even you don't know the answer.
More exercises
- From 1 to N. Read N and print the numbers from 1 to N on one line. For 5:
1 2 3 4 5. - Factorial. N! = 1 · 2 · 3 · … · N. For 5: 120. In Python a whole number has no upper limit: 20! is 2432902008176640000, and 30! comes out just as exact.
- Primes up to N. Print all prime numbers up to N. For 20:
2 3 5 7 11 13 17 19. The check from exercise 2 goes inside a loop over the numbers: nested loops. - Fibonacci. Each number is the sum of the two before it: 0, 1, 1, 2, 3, 5, 8… Read N and print the first N numbers. For 10:
0 1 1 2 3 5 8 13 21 34. - Square of stars. Read N and print an N × N square. For 3:
* * ** * ** * *- Triangle of stars. The same, but each row has as many stars as its number. For 3:
** ** * *- Coin toss. Read N, toss a coin N times with a random number (0 is heads, 1 is tails) and print how many times each came up. The bigger N is, the closer both numbers get to N / 2.
- Rock, paper, scissors. A player against the computer. The player types a choice, the computer picks at random, and the program says who wins. With while True and break it asks "Another game? (yes/no)" and at the end prints the score.
Test