Lesson 5 of 16 · Level 2: Intermediate
Python for and while Loops: range, break and continue
- ⏱ 13 min read
- ❓ 4 review questions
- ✍️ Exercise with solution
In this lesson
- for: walking through items
- range(): repeat a set number of times
- Accumulators and counters
- enumerate(): index and value together
- while: repeat as long as a condition is true
- break and continue
- Nested loops
- List comprehensions: a loop on one line
- Real case: a Boston bakery's weekly summary
- Common loop mistakes
- Summary
- Loop over collections with for and range().
- Calculate totals and counts with accumulators.
- Repeat while a condition holds with while, break and continue.
- Transform and filter lists with list comprehensions.
- Analyze a week of sales for a small business and draw a bar chart in the terminal.
Loops repeat a block of code. They're why processing 1,000 invoices takes the same effort as processing one. Python has two kinds: for, to walk through a collection or a known range, and while, to keep going as long as a condition is true. In this lesson you'll use both, and finish with a weekly sales report for a Boston bakery.
for when you know what to walk through, while when it depends on a conditionfor: walking through items
Python's for loop goes through any sequence one item at a time:
cities = ["Austin", "Denver", "Miami"]
for city in cities:
print(f"Shipping to {city}")
Shipping to Austin
Shipping to Denver
Shipping to Miami
On each pass (called an iteration), the variable city takes the next value from the list. It also works with strings (character by character) and with every collection you'll see in lesson 6. Name the loop variable as the singular of the list: for invoice in invoices reads like English.
range(): repeat a set number of times
for i in range(5):
print(i) # 0, 1, 2, 3, 4
for i in range(1, 6):
print(i) # 1, 2, 3, 4, 5
for i in range(0, 20, 5):
print(i) # 0, 5, 10, 15
for i in range(10, 0, -1):
print(i) # countdown from 10 to 1
Just like string slices, range(start, stop, step) includes the start and excludes the stop.
Example: a multiplication table
n = int(input("Number: "))
for i in range(1, 11):
print(f"{n} x {i:2} = {n * i:3}")
The :2 and :3 inside the f-string reserve 2 and 3 characters, so the columns line up. With 7, the last line is 7 x 10 = 70.
1. Which numbers does range(1, 5) produce?
range(start, stop) includes the start and excludes the stop.
Accumulators and counters
Here's a pattern you'll use constantly: a variable that starts at zero and is updated on every pass.
sales = [120.50, 89.90, 230.00, 45.00, 310.20]
total = 0
big_sales = 0
for sale in sales:
total += sale
if sale > 100:
big_sales += 1
print(f"Total sold: ${total:,.2f}")
print(f"Sales over $100: {big_sales}")
print(f"Average: ${total / len(sales):,.2f}")
Total sold: $795.60
Sales over $100: 3
Average: $159.12
For simple cases, Python already has built-in functions that do this for you: sum(sales), max(sales), min(sales) and len(sales). The manual pattern is still worth knowing, because real reports usually need a condition inside the loop, like counting only the big sales.
enumerate(): index and value together
tasks = ["Answer emails", "Team meeting", "Write report"]
for number, task in enumerate(tasks, start=1):
print(f"{number}. {task}")
1. Answer emails
2. Team meeting
3. Write report
while: repeat as long as a condition is true
Use while when you don't know in advance how many passes you'll need. How many periods does it take for $1,000 to double at 5% per period?
balance = 1000
period = 0
while balance < 2000:
balance *= 1.05 # grows 5% each period
period += 1
print(f"It doubles in {period} periods: ${balance:,.2f}")
It doubles in 15 periods: $2,078.93
Remember the Rule of 72? 72 ÷ 5 = 14.4 periods, very close. If you want to see why compound growth matters so much for your own money, our personal finance course has a lesson on compound interest and inflation.
If a while condition never becomes false, the program never ends. Make sure something inside the loop moves the condition toward False. If it happens anyway, stop the program with Ctrl + C in the terminal.
Validating user input
age = int(input("Age (0-120): "))
while age < 0 or age > 120:
print("Value out of range")
age = int(input("Age (0-120): "))
print("Thank you")
break and continue
- What it does
- Ends the loop immediately; the program continues on the first line after the loop.
- Use it to
- Stop once you've found what you were looking for or the user chose "Quit."
- What it does
- Ignores the rest of the block for this pass and moves on to the next one.
- Use it to
- Skip bad data (blank or invalid rows) without stopping the whole process.
# A menu that repeats until the user chooses to quit
while True:
option = input("1) Say hi 2) Quit: ")
if option == "2":
break
if option != "1":
print("Invalid option")
continue
print("Hi there!")
print("Goodbye")
1) Say hi 2) Quit: 1
Hi there!
1) Say hi 2) Quit: 5
Invalid option
1) Say hi 2) Quit: 2
Goodbye
The while True + break pattern is very common for menus and for "keep asking until the input is valid."
2. What does continue do inside a loop?
continue jumps to the next pass; break exits the loop entirely.
Nested loops
A loop inside another loop. The inner one runs completely on every pass of the outer one:
for row in range(1, 4):
line = ""
for col in range(1, 4):
line += f"{row * col:4}"
print(line)
1 2 3
2 4 6
3 6 9
If the outer loop runs 1,000 times and the inner loop another 1,000, that's a million operations. With big data, it pays to ask whether there's a more efficient approach (pandas, in lesson 11, is one).
List comprehensions: a loop on one line
A compact, very "Pythonic" way to build a list from another list. Here's a price list with 8.25% sales tax added, and a filter for items over $90:
prices = [100, 250, 80, 40]
with_tax = [round(p * 1.0825, 2) for p in prices]
expensive = [p for p in prices if p > 90]
print(with_tax) # [108.25, 270.62, 86.6, 43.3]
print(expensive) # [100, 250]
Read it as "give me round(p * 1.0825, 2) for each p in prices." Use comprehensions for simple transformations and filters. If the logic gets complicated, a regular for is easier to read.
3. What does [n * 2 for n in [1, 2, 3] if n > 1] return?
It filters first (2 and 3 pass n > 1) and then transforms them (× 2).
Real case: a Boston bakery's weekly summary
Beacon Hill Bakery in Boston writes down its sales every night. With a single for loop you can calculate the total, find the best day and even draw a bar chart in the terminal. There's one new tool here: zip(), which walks through two lists at once and hands you a day and its sales on each pass.
# One week of sales - Beacon Hill Bakery (Boston), in dollars
days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
sales = [1_240, 1_085, 1_190, 1_310, 1_760, 2_280, 1_540]
total = 0
best_day = ""
best_sale = 0
for day, sale in zip(days, sales):
total += sale
if sale > best_sale:
best_sale = sale
best_day = day
bar = "#" * (sale // 100)
print(f"{day} {bar:<23} {sale:>6,}")
average = total / len(sales)
above_average = [d for d, s in zip(days, sales) if s > average]
print(f"Weekly total: ${total:,}")
print(f"Daily average: ${average:,.2f}")
print(f"Best day: {best_day} (${best_sale:,})")
print("Days above average:", ", ".join(above_average))
Output:
Mon ############ 1,240
Tue ########## 1,085
Wed ########### 1,190
Thu ############# 1,310
Fri ################# 1,760
Sat ###################### 2,280
Sun ############### 1,540
Weekly total: $10,405
Daily average: $1,486.43
Best day: Sat ($2,280)
Days above average: Fri, Sat, Sun
How each piece works:
- Accumulator:
totalstarts at 0 and adds each day's sales. - Finding the maximum: if today beats the best day so far, it becomes the new best. That's the logic behind
max(), but here we also keep which day it was. - Text chart:
"#" * (sale // 100)draws one symbol per $100;:<23pads with spaces to align the columns and:>6,right-aligns the amounts. - Comprehension with a filter: picks the days whose sales beat the average.
The same summary as a chart (green marks the days above the $1,486 average):
The business takeaway jumps out: Friday through Sunday bring in more than half the week ($5,580 of $10,405, or 53.6%), so that's when it pays to bake more and schedule extra staff.
4. What does this code print?
for sale in [100, 200, 300]:
total = 0
total += sale
print(total)
The accumulator resets to 0 on every pass because it's inside the loop, so only the last sale survives. Create total = 0 before the for.
Common loop mistakes
The classic bug is running off the end of a list. If you loop over positions with range(1, len(sales) + 1) to "start at 1," the last pass asks for a position that doesn't exist:
Traceback (most recent call last):
File "sales.py", line 3, in <module>
print(sales[i])
~~~~~^^^
IndexError: list index out of range
A 3-item list has positions 0, 1 and 2. On top of the crash, that loop silently skipped the first item. The fix is to loop over the items directly (for sale in sales) or use enumerate(sales, start=1) if you need numbering from 1.
Creating the accumulator inside the loop.
total = 0 goes before the for; inside, you only update it.
Writing for i in 5:
You can't loop over a number (TypeError: 'int' object is not iterable). Use for i in range(5):.
Forgetting to update a while loop's variable.
Make sure something inside the loop moves the condition toward False (period += 1, a new input()…).
Using range(len(items)) and items[i] for everything.
Loop over the items directly; use enumerate() or zip() when you need the position or two lists.
Adding or removing items from a list while looping over it.
Build a new list (for example, with a comprehension) and replace the original when you're done.
Practice exercise: a number-guessing game
The program picks a random number between 1 and 50. The user tries to guess it; after each attempt, the program says "Higher" or "Lower." When the user gets it right, show how many tries it took. Maximum of 7 tries.
Hint: for the random number, use import random and random.randint(1, 50).
See solution
import random
secret = random.randint(1, 50)
MAX_TRIES = 7
for attempt in range(1, MAX_TRIES + 1):
number = int(input(f"Try {attempt}/{MAX_TRIES}: "))
if number == secret:
print(f"Correct! You got it in {attempt} tries")
break
elif number < secret:
print("Higher")
else:
print("Lower")
else:
print(f"Out of tries. It was {secret}")
A sample run where the secret was 16: guessing 25 prints "Lower," 12 prints "Higher" and 16 prints Correct! You got it in 3 tries. Fun fact: a for loop's else only runs if the loop finished without a break, which here means the user never guessed right.
Summary
forwalks through a collection or arange();whilerepeats as long as a condition is true.- Accumulators and counters handle totals and counts;
sum,max,minandlencover the simple cases. breakexits the loop;continueskips to the next pass.- List comprehensions transform and filter in a single line.
zip()walks two lists in parallel;enumerate()gives you the position and the value.
Next lesson: Python Lists, Tuples, Dictionaries and Sets. You'll learn Python's four built-in data structures, their most useful methods and when to use each one.
Create your account in 30 seconds, mark your lessons and download your certificate at the end.