Python loops — exercises with FizzBuzz, a growing investment, primes and a savings plan (and the break that only left the tray)
In an FP1 mock exam I got a search exercise: “go through the trays on the counter and say where the first chocolate croissant is”. Two loops, one inside the other, and a break when it’s found. I handed it in without a worry. When it was marked, my program had found two “first” croissants. The break worked, yes… but it only got me out of the tray loop; the outer one happily moved on to the next tray. You’ll find it in “What’s wrong here?”, with the fix and a diagram of which pieces each version checks.
You already have the theory and the practice of Python loops. Now it’s your turn: four exercises on three levels (basic, intermediate and final challenge), three snippets with a hidden bug, solutions commented line by line and a cheat sheet to keep everything at hand. All the programs use fixed data, no input(), and the outputs you see come from their real run.
Table of Contents
How to use this article
- Read the statement and the expected output, and write your solution in VS Code without looking at anything else.
- If you’ve been stuck for more than 10 minutes, open the hint (and only the hint).
- Compare your output with the expected one character by character: one number too many or too few is usually a badly closed
range. - Read the commented solution even if yours worked: there’s often a decision you hadn’t thought of.
Basic level
Exercise 1: FizzBuzz
FizzBuzz is probably the most famous programming exercise in the world; it’s even used as a filter in job interviews. Write a program that goes through the numbers 1 to 100 and, for each one:
- if it’s divisible by 3 and by 5, writes
FizzBuzz; - if it’s only divisible by 3,
Fizz; - if it’s only divisible by 5,
Buzz; - otherwise, the number itself.
So the output doesn’t take 100 lines, write the results separated by spaces and break the line every 10 numbers. Expected output:
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz
for i in range(1, 101): you know there are 100 numbers (and the stop is left out). The trick is the order of the if/elif: the “divisible by 3 and by 5” case has to come first. To avoid a line break after every number, print(text, end=" "); to break every 10, an if i % 10 == 0: print().
Exercise 2: Compound interest calculator
The café tip jar has collected 1,000 €, which goes into an account at 5 % a year for 5 years. With compound interest, each year’s interest is added to the capital and earns interest itself the following year: capital = capital × (1 + interest / 100). Write a program that shows the capital at the end of each year (rounded to 2 decimals) with what was earned that year, and at the end the capital, the total earned and the return as a percentage. Expected output:
--- Investment growth --- Year 1: 1050.00 € (+50.00 €) Year 2: 1102.50 € (+52.50 €) Year 3: 1157.62 € (+55.12 €) Year 4: 1215.50 € (+57.88 €) Year 5: 1276.28 € (+60.78 €) Final capital: 1276.28 € Total earned: 276.28 € Return: 27.63 %
for year in range(1, years + 1), because you know how many years there are. For each year’s gain you need the capital from before it’s updated: save it in another variable at the start of the pass. Round with round(…, 2) every year, as a bank would.
Intermediate level
Exercise 3: Prime number finder
A number is prime if it’s only divisible by 1 and itself. Write a program that finds all the primes from 2 to 30, shows them on one line, says how many there are and counts how many divisions (%) it had to do in total. Expected output:
Primes up to 30: 2 3 5 7 11 13 17 19 23 29 Total: 10 primes Divisions done: 45
Two nested loops. The outer one goes through the candidates from 2 to 30; the inner one tries divisors. Use a flag is_prime = True that becomes False if you find a divisor, and a break at that moment (no need to keep going with that number). It’s enough to try divisors up to the square root: range(2, int(number ** 0.5) + 1). If you get more than 45 divisions, you’re missing the break or the square-root limit.
Final challenge
Exercise 4: Monthly savings simulator
The café wants a new 10,000 € coffee machine. Every month 300 € is saved into an account at 4 % a year. Each month, the 300 € goes in first and then the monthly interest is applied (the annual rate divided by 12), rounding the balance to 2 decimals. How many months will it take to reach the goal? Show the balance from the third year on (month 25 onwards) up to the month the goal is reached, the time in years and months, the amount saved, the amount paid in and the interest. And if the monthly saving were 0 or negative, the program must warn you instead of hanging. Expected output:
Month 25: 7833.84 € Month 26: 8160.95 € Month 27: 8489.15 € Month 28: 8818.45 € Month 29: 9148.84 € Month 30: 9480.34 € Month 31: 9812.94 € Month 32: 10146.65 € Goal reached in 32 months (2 years and 8 months) Saved: 10146.65 € | paid in: 9600.00 € Interest: 546.65 €
You don’t know how many months it will take, so while balance < goal:. The monthly interest is 4 / 12 / 100. For years and leftover months, months // 12 and months % 12 (you saw them in operators). And think about what would happen with monthly_saving = 0: the balance would never grow and the while would never end, so check it with an if before the loop.
What’s wrong here?
Three short snippets, each with a typical loop bug. Before reading the explanation, predict what they print.
Snippet 1: the days that don’t add up
We want to add up the sales of days 1 to 10, at 100 € a day:
# I want to add up the sales of days 1 to 10 (100 € a day)
total = 0
for day in range(1, 10):
total += 100
print("Last day added:", day)
print("Total:", total, "€")
What does it print? Think before reading on.
Real output:
Last day added: 9 Total: 900 €
100 € is missing: day 10 was never added. range(1, 10) produces 1 to 9, because the stop is never included. That’s why day ends at 9 and the total is 9 × 100 = 900.
The off-by-one error. If you want to reach N, the range stop is N + 1.
The fix is changing the 10 to 11:
# Fixed: range's stop is left out, so to reach 10 you write 11
total = 0
for day in range(1, 11):
total += 100
print("Last day added:", day)
print("Total:", total, "€")
Output:
Last day added: 10 Total: 1000 €
To check a range without running the whole loop, print list(range(1, 10)) or len(range(1, 10)). If len doesn’t give the days you expect, that’s where the bug is.
Snippet 2: the first chocolate croissant
This is the one from my story. The trays are texts: each letter is a piece (P plain, C chocolate). We want the first chocolate croissant and then stop:
# I look for the FIRST chocolate croissant (C) and want to stop as soon as I find it
trays = ["PPC", "CPC", "PPP"] # P = plain, C = chocolate
num = 0
for tray in trays:
num += 1
slot = 0
for piece in tray: # a for also walks through a text, letter by letter
slot += 1
if piece == "C":
print(f"Chocolate: tray {num}, slot {slot}")
break
print("Search finished")
How many “Chocolate” lines will come out?
Real output:
Chocolate: tray 1, slot 3 Chocolate: tray 2, slot 1 Search finished
Two. The break gets out of the pieces loop (for piece in tray), but not out of the trays loop: the outer one makes its next pass, goes into tray 2 and finds another chocolate. break only ends the innermost loop it’s in. The diagram compares which pieces each version gets to check:
Expecting a break inside two loops to end both. It only ends the inner one.
The fix: a flag that the inner loop sets to True and the outer loop checks after each tray:
# Fixed: a flag tells the outer loop that we are done
trays = ["PPC", "CPC", "PPP"] # P = plain, C = chocolate
num = 0
found = False
for tray in trays:
num += 1
slot = 0
for piece in tray:
slot += 1
if piece == "C":
print(f"Chocolate: tray {num}, slot {slot}")
found = True
break # leaves the pieces loop...
if found:
break # ...and this one, the trays loop
print("Search finished")
Output:
Chocolate: tray 1, slot 3 Search finished
Once you know functions (the next topic), there’s an even cleaner way: put the search inside a function and use return, which leaves all the loops at once.
Snippet 3: the total that forgets
Adding up the morning tickets:
# Add up the morning tickets
tickets = [3.50, 1.20, 4.80]
for ticket in tickets:
total = 0
total += ticket
print(f"Total: {total:.2f} €")
What’s the total?
Real output:
Total: 4.80 €
4.80 €: only the last ticket. total = 0 is inside the loop, so it resets on every pass before adding. At the end of pass 3, total is 0 + 4.80. What was added on passes 1 and 2 is lost.
Initialising the accumulator inside the loop. It goes before, level with the for.
# Fixed: the accumulator is created ONCE, before the loop
tickets = [3.50, 1.20, 4.80]
total = 0
for ticket in tickets:
total += ticket
print(f"Total: {total:.2f} €")
Output:
Total: 9.50 €
Check: 3.50 + 1.20 + 4.80 = 9.50 €.
Commented solutions
Solution to exercise 1: FizzBuzz
# Basic level · Exercise 1: FizzBuzz from 1 to 100, ten per line
for i in range(1, 101): # 101 so that 100 is included
if i % 3 == 0 and i % 5 == 0: # the double case FIRST: otherwise 15 would stay as "Fizz"
text = "FizzBuzz"
elif i % 3 == 0:
text = "Fizz"
elif i % 5 == 0:
text = "Buzz"
else:
text = str(i) # the number as it is, as text
print(text, end=" ") # everything on the same line...
if i % 10 == 0:
print() # ...until we reach a multiple of 10
Why it’s done this way:
- The order of the conditions. 15 is divisible by 3 and by 5. If the first question were
i % 3 == 0, 15 would go in there, write “Fizz” and theelifs below wouldn’t even be looked at. That’s why the double case comes first. Another equivalent way:i % 15 == 0(divisible by 3 and by 5 is the same as divisible by 15). - One
textvariable and a singleprint. Each branch only decides which text it is; theprintappears once, at the end. If you change the format tomorrow, you change it in one place. str(i). In the other branchestextis a text; this way all four branches leave the same type in the variable.- The line break.
end=" "keeps everything on the same line, andif i % 10 == 0: print()breaks at 10, 20… The emptyprint()only prints the line break.
Checking the first line: 3, 6 and 9 → Fizz; 5 and 10 → Buzz; the rest, numbers. On the second line, 15 → FizzBuzz.
Solution to exercise 2: Compound interest
# Basic level · Exercise 2: compound interest year by year
initial_capital = 1000.0
interest = 5.0 # % per year
years = 5
capital = initial_capital # the capital that keeps growing (the initial one is not touched)
print("--- Investment growth ---")
for year in range(1, years + 1): # we know how many years: for
previous = capital # saved BEFORE updating, for the year's gain
capital = round(capital * (1 + interest / 100), 2)
gain = round(capital - previous, 2)
print(f"Year {year}: {capital:.2f} € (+{gain:.2f} €)")
total = round(capital - initial_capital, 2)
print(f"Final capital: {capital:.2f} €")
print(f"Total earned: {total:.2f} €")
print(f"Return: {total / initial_capital * 100:.2f} %")
Why it’s done this way:
for, notwhile: we know there are 5 years.capitalandinitial_capitalkept apart:capitalkeeps changing, but at the end we need the initial one to work out what was earned and the return.previousis saved at the start of the pass: aftercapital = …the old value no longer exists. Withoutprevious, we couldn’t know what was earned that year.round(…, 2)every year, as a bank would: the next year is computed on the already-rounded capital.
Pass-by-pass trace:
| Year | previous | capital × 1.05 | capital (rounded) | gain |
|---|---|---|---|---|
| 1 | 1000.00 | 1050.0 | 1050.00 | 50.00 |
| 2 | 1050.00 | 1102.5 | 1102.50 | 52.50 |
| 3 | 1102.50 | 1157.625 | 1157.62 | 55.12 |
| 4 | 1157.62 | 1215.501 | 1215.50 | 57.88 |
| 5 | 1215.50 | 1276.275 | 1276.28 | 60.78 |
Why does year 3 round to 1157.62 and not 1157.63? Because 1157.625 can’t be stored exactly in a float: in memory it’s something like 1157.62499999…, and round rounds it down. It’s the same float issue we saw in variables and data types. The return: 276.28 / 1000 × 100 = 27.63 %.
If you need exact cents (as with the till change in the theory), work in whole cents and divide by 100 only when displaying.
Solution to exercise 3: Prime numbers
# Intermediate level · Exercise 3: prime numbers up to n
n = 30
primes = []
checks = 0 # how many divisions it does in total
for number in range(2, n + 1): # outer loop: each candidate
is_prime = True # innocent until proven otherwise
for divisor in range(2, int(number ** 0.5) + 1): # going up to the root is enough
checks += 1
if number % divisor == 0:
is_prime = False
break # there is a divisor: no need to go on with THIS number
if is_prime:
primes.append(number)
text = ""
for p in primes:
text += str(p) + " "
print(f"Primes up to {n}: {text}")
print(f"Total: {len(primes)} primes")
print(f"Divisions done: {checks}")
Why it’s done this way:
- The
is_primeflag is set toTrueat the start of each outer pass. Every candidate starts out “innocent”. If you set it before the outer loop, as soon as one number wasn’t prime (4), all the others would be marked as not prime. - The
breakcuts the divisors loop as soon as one shows up: 30 is known not to be prime after dividing by 2, no need to try 3, 4 and 5. That’s why there are 45 divisions and not many more. - Up to the square root: if a number has a divisor greater than its root, it also has a smaller one (for example, 28 = 2 × 14), and we’d already have found that one.
int(number ** 0.5) + 1is the usualrange+ 1. - For 2 and 3, the inner loop is empty (
range(2, 2)): it makes no passes, the flag staysTrueand they’re counted as primes, which is correct.
This is where break acts for each number:
Zooming into the two loops:
for number in range(2, n + 1): # outer loop: each candidate
is_prime = True # innocent until proven otherwise
for divisor in range(2, int(number ** 0.5) + 1): # going up to the root is enough
checks += 1
if number % divisor == 0:
is_prime = False
break # there is a divisor: no need to go on with THIS number
if is_prime:
primes.append(number)
| number | divisors tried | break? | is_prime |
|---|---|---|---|
| 2, 3 | none (empty range) | — | True |
| 4 | 2 | yes, at 2 | False |
| 9 | 2, 3 | yes, at 3 | False |
| 25 | 2, 3, 4, 5 | yes, at 5 | False |
| 29 | 2, 3, 4, 5 | no | True |
Solution to exercise 4: Savings simulator
# Final challenge · Exercise 4: how many months to reach the goal?
goal = 10000.0
monthly_saving = 300.0
annual_interest = 4.0 # %
if monthly_saving <= 0: # with 0 € a month the while would never end
print("Error: monthly savings must be greater than 0")
else:
monthly_interest = annual_interest / 12 / 100
balance = 0.0
month = 0
paid_in = 0.0
while balance < goal: # we don't know how many months: while
month += 1
balance += monthly_saving # 1st the month is paid in
balance = round(balance * (1 + monthly_interest), 2) # 2nd interest is applied
paid_in += monthly_saving
if month > 24: # we only show the last months
print(f"Month {month}: {balance:.2f} €")
years = month // 12
remainder = month % 12
print(f"Goal reached in {month} months ({years} years and {remainder} months)")
print(f"Saved: {balance:.2f} € | paid in: {paid_in:.2f} €")
print(f"Interest: {balance - paid_in:.2f} €")
Why it’s done this way:
- The
ifbefore thewhile: withmonthly_saving <= 0the balance would never grow andbalance < goalwould beTrueforever. It’s checked before going in, not inside. while, notfor: we don’t know how many months it takes; that’s precisely what we want to find out.- The order inside the pass: first the money goes in, then the interest is applied, as the statement says. The other way round you’d get a different number of months (that month’s 300 € wouldn’t earn interest that month).
monthstarts at 0 and is added at the start of the pass: so when the loop ends,monthis exactly the number of months simulated.if month > 24inside the loop: decides which months are printed without having to store the history.
Zooming into the loop:
while balance < goal: # we don't know how many months: while
month += 1
balance += monthly_saving # 1st the month is paid in
balance = round(balance * (1 + monthly_interest), 2) # 2nd interest is applied
paid_in += monthly_saving
if month > 24: # we only show the last months
print(f"Month {month}: {balance:.2f} €")
Check: 32 months are 32 // 12 = 2 years and 32 % 12 = 8 months. Paid in: 32 × 300 = 9,600 €. Interest: 10,146.65 − 9,600 = 546.65 €. In month 31 the balance (9,812.94 €) still hasn’t reached 10,000, so the loop makes one more pass; in month 32 it goes over and the condition 10146.65 < 10000.0 is now False.
Exam-style quiz
Now test yourself as in the exam. The FP1 quizzes look like this: 15 questions in 20 minutes (16 in 30 in the Sequences one), almost all single choice (each wrong answer subtracts a third of what the question is worth) and many «what does this code print?», with the odd fill in the gaps, matching or true or false. Here are 13 original questions on loops. Answer without running anything, press Check and read the explanation for each one. These questions are also the question bank for the FP1 theory mock exam, which will mix them with those from the other topics.
What is the value of x at the end? Write only the number.
x = 0
i = 1
while i < 5:
x += i
i += 1
print(x)Solution
Answer: 10
The loop adds i while i < 5: 1 + 2 + 3 + 4 = 10. When i reaches 5, the condition is false and the loop ends without adding it.
Which numbers does range(2, 10, 3) produce?
- 2, 5 and 8
- 2, 5, 8 and 11
- 2, 3, 4, 5, 6, 7, 8 and 9
- 3, 6 and 9
Solution
Answer: 2, 5 and 8
range(start, stop, step): it starts at start, adds step each time and does not include stop. That is why range(5) gives 0, 1, 2, 3 and 4.
How many times is hello printed? Write only the number.
for i in range(3):
for j in range(4):
print("hello")Solution
Answer: 12
For each of the 3 turns of the outer loop, the inner one does 4 turns: 3 × 4 = 12. In nested loops, the turns multiply.
What does this code print?
for n in range(1, 10):
if n % 4 == 0:
break
print(n, end=" ")1 2 31 2 3 41 2 3 5 6 7 94 8
Solution
Answer: 1 2 3
break ends the whole loop as soon as it runs. continue, on the other hand, skips the rest of that turn and carries on with the next one.
What does this program print? Write the exact output.
s = 0
for n in range(1, 8):
if n % 2 == 0:
continue
s += n
print(s)Solution
Answer: 16
continue skips the even numbers, so only the odd ones from 1 to 7 are added: 1 + 3 + 5 + 7 = 16.
When is a while better than a for?
- When you do not know in advance how many turns the loop will take
- When you want to go through a list
- Never:
whileis an old form offor - When the loop has a fixed number of turns
Solution
Answer: When you do not know in advance how many turns the loop will take
for = «do this for each element» (or a fixed number of times). while = «repeat while the condition holds». With while, remember to change something inside the loop or it will never end.
What is wrong with this program?
i = 10
while i > 0:
print(i)
i -= 1- It never ends:
i -= 1is outside the loop andiis always 10 - It prints 10 down to 1
- It only prints 10
- It is a syntax error
Solution
Answer: It never ends: i -= 1 is outside the loop and i is always 10
It is an infinite loop: the condition i > 0 never stops holding because i does not change inside the loop. In the terminal you stop it with Ctrl + C.
True or false?
for letter in 'code':does 4 turns.range(5)includes 5.- A
whilewhose condition is false from the start does not do any turn. breakinside two nested loops leaves both.
Solution
- T —
for letter in 'code':does 4 turns. - F —
range(5)includes 5. - T — A
whilewhose condition is false from the start does not do any turn. - F —
breakinside two nested loops leaves both.
A for goes through any sequence, text included (one turn per character). range(5) goes from 0 to 4. And break only leaves the loop it is in: the outer one carries on.
What does this code print?
n = 1
while n < 100:
n = n * 3
print(n)2438199100
Solution
Answer: 243
The while checks the condition before each turn. With n = 81, 81 < 100 is true and it goes in: n = 243. Then 243 < 100 is false and it leaves. The final value can go past the limit.
Complete the loop so that it adds the numbers from 1 to 10 (both included):
total = 0 and then for i in range(1, ____): with total ____ i inside.
Words:
- =
- +=
- 11
- 10
- -=
Solution
total = 0 and then for i in range(1, 11): with total += i inside.
Since the end of range is not included, to reach 10 you must write 11. And total += i accumulates; with total = i you would only keep the last one.
What does this code print?
count = 0
for c in "Gran Canaria":
if c == "a":
count += 1
print(count)4532
Solution
Answer: 4
It is the counter pattern: start at 0 and add 1 every time the condition holds. Since 'a' == 'A' is false, capitals would not count.
What does this program print? Write the exact output.
biggest = 0
for n in [4, 17, 9, 23, 8]:
if n > biggest:
biggest = n
print(biggest)Solution
Answer: 23
It is the maximum pattern: you keep the best seen so far and change it when a bigger one appears. 4 → 17 → (9 no) → 23 → (8 no): 23 remains.
What does the else of this loop do?
for n in [3, 7, 11]:
if n % 2 == 0:
print("found an even one")
break
else:
print("none is even")- It runs because the loop finished without going through the
break - It runs on every turn in which the
ifis false - It is an error: a
forcannot have anelse - It never runs
Solution
Answer: It runs because the loop finished without going through the break
The else of a for (or a while) runs when the loop ends normally, without break. It is great for searches: «if I have not found it…».
Watch it step by step in Python Tutor
On pythontutor.com, with Python 3, you can watch snippet 2’s bug live. Paste this short version:
# For Python Tutor: the break that only leaves the inner loop
trays = ["PPC", "CPC", "PPP"]
num = 0
for tray in trays:
num += 1
slot = 0
for piece in tray:
slot += 1
if piece == "C":
print(num, slot)
break
print("end")
Output:
1 3 2 1 end
What to watch step by step:
- In the first tray,
piecetakes “P”, “P” and “C”: aforover a text goes through its letters. - When
pieceis “C”,1 3is printed and the arrow jumps from thebreakto the outerfor trayline, not toprint("end"). numbecomes 2 andslotgoes back to 0: the outer loop carries on as if nothing happened.- In tray 2 the chocolate is in the first slot: a second
print(2 1) and a secondbreak. - Tray 3 is walked through completely (no “C”) and finally
endis printed. Now try the flag version and watch the arrow leave both loops.
Cheat sheet: Python loops
The essentials in 30 seconds: for when you know how many passes there will be (it walks a sequence or a range); while when you don’t (it repeats while the condition is True, and something inside has to make it false). range never includes the stop. break leaves the loop (only the innermost); continue skips to the next item. Accumulators are prepared before the loop.
| I want to… | Code | Result |
|---|---|---|
| Walk through a list | for t in [3.5, 1.2]: print(t) | 3.5 and 1.2 |
| Repeat N times | for i in range(3): print(i) | 0, 1, 2 |
| From 1 to 10 | range(1, 11) | 1 … 10 |
| Count down | range(5, 0, -1) | 5, 4, 3, 2, 1 |
| In twos | range(0, 11, 2) | 0, 2, 4, 6, 8, 10 |
| Repeat while something holds | while queue > 0: queue -= 2 | stops when queue ≤ 0 |
| Leave when something is found | if t > 5: break | ends the loop |
| Skip one case | if t == 0: continue | goes to the next one |
| “Do while” | while True: … if ok: break | at least one pass |
| Print on the same line | print(x, end=" ") | no line break |
| Pattern | Before the loop | Inside the loop |
|---|---|---|
| Sum | total = 0 | total += x |
| Counter | n = 0 | if cond: n += 1 |
| Product | p = 1 | p *= x |
| Maximum | highest = items[0] | if x > highest: highest = x |
| Text | text = "" | text += str(x) + " " |
| Search in two loops | found = False | found = True, break and, outside, if found: break |
Exercise templates:
- FizzBuzz:
for i in range(1, 101):+if i % 3 == 0 and i % 5 == 0:first → 10 lines of 10. - Compound interest:
previous = capital→capital = round(capital * (1 + interest / 100), 2)→ 1276.28 € in 5 years. - Primes: an
is_prime = Trueflag per candidate +for divisor in range(2, int(n ** 0.5) + 1)+break→ 10 primes up to 30, 45 divisions. - Savings:
if saving <= 0first +while balance < goal:+month // 12andmonth % 12→ 32 months.
| Symptom | Likely cause |
|---|---|
| The program never ends | while that doesn’t update the variable, or continue before the update |
| The last number is missing | range(1, n) instead of range(1, n + 1) |
| The loop does nothing and there’s no error | Empty range: range(5, 0) without -1, or a while condition false from the start |
| The total is only the last value | Accumulator initialised inside the loop |
| It finds “the first one” several times | break inside two loops: it only leaves the inner one |
| Everything is 0 when multiplying | Product accumulator starting at 0 |
NameError with the accumulator | It wasn’t initialised before the loop |
IndexError in a while over a list | The condition lets one pass too many through (<= instead of <, or or instead of and) |
Before handing it in, ask yourself:
- Do I know how many passes each loop makes? Did I choose
fororwhilebecause of that? - In each
while, which line moves the condition towardsFalse, and does it run on every pass? - Do my
ranges reach exactly where I want (the stop is left out)? - Are my accumulators initialised before the loop with the right value (0, 1 or
"")?
If you still have doubts, go back to the loops theory or review the practice. And if you’ve got it, the next topic is Python functions: what we repeat with loops today, we’ll store under its own name tomorrow.
Keep goingAll Python articlesDid this article help you? Here is how you can support SergioLearns →




What is an operating system — theory with your laptop on a study afternoon, a write() call and a CPU that never rests (and the three programs that weren’t running at the same time)