Lesson 5 • Beginner
Loops: Repeating Code in Python
Learn how to make Python repeat tasks automatically using for and while loops.
What You'll Learn in This Lesson
- ✓How for loops repeat code for each item in a sequence
- ✓How range() generates number sequences
- ✓How while loops repeat until a condition changes
- ✓When to use for vs while
- ✓How break exits a loop early and continue skips an iteration
- ✓How to loop through lists, strings, and dictionaries
What Are Loops?
Loops let you repeat code multiple times without writing it over and over. Instead of writing print("Hello") 100 times, you can use a loop to do it once.
Real-world analogy:
Think of loops like a washing machine cycle. It repeats the same steps (wash, rinse, spin) until the clothes are clean. Your code works the same way!
Python has two main types of loops:
for loop
Use when you know how many times to repeat
"Do this 10 times" or "Do this for each item"
while loop
Use when you repeat until a condition changes
"Keep asking until user says stop"
🧠 How Loops Execute: The Mental Model
Before writing loops, build a clear picture of what Python is actually doing each time through. This mental model prevents most beginner loop bugs.
The loop variable is reassigned every iteration
Each time the loop runs, the loop variable gets the next value from the sequence. Python handles this automatically — you just use it.
The indented block is one "iteration"
Everything indented under for or while is the loop body. It runs once per value. Code at the original indentation level runs after the loop finishes.
The loop variable still exists after the loop
After a for loop finishes, the loop variable holds the last value it had. This is sometimes useful — but can also cause bugs if you forget.
Trace through this step by step:
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit.upper())
print("Done:", fruit)Execution trace:
① fruit = "apple" → prints APPLE
② fruit = "banana" → prints BANANA
③ fruit = "cherry" → prints CHERRY
④ Sequence exhausted → loop exits
⑤ print("Done:", fruit) → Done: cherry
1. The for Loop
The for loop repeats code for each item in a sequence (like a list or range of numbers).
# Syntax:
for variable in sequence:
code to repeat
| Part | Description |
|---|---|
| for | Keyword that starts the loop |
| variable | Holds the current item (you choose the name) |
| in | Keyword connecting variable to sequence |
| sequence | What to loop over (list, range, string, etc.) |
| : | Required colon at the end |
Try It: Basic for Loop
Loop through items in a list
# Loop through a list
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(f"I like {fruit}!")
print("Done with fruits!")
# The variable 'fruit' takes each value in turn:
# First loop: fruit = "apple"
# Second loop: fruit = "banana"
# Third loop: fruit = "cherry"2. The range() Function
range() generates a sequence of numbers. It's the most common way to repeat code a specific number of times.
| Syntax | What It Produces | Example |
|---|---|---|
| range(stop) | 0 to stop-1 | range(5) → 0,1,2,3,4 |
| range(start, stop) | start to stop-1 | range(2, 6) → 2,3,4,5 |
| range(start, stop, step) | start to stop-1, by step | range(0, 10, 2) → 0,2,4,6,8 |
range(5) goes from 0 to 4, not 0 to 5.Try It: range() Function
See different ways to generate number sequences
# Different ways to use range()
# Count 0 to 4
print("range(5):")
for i in range(5):
print(i, end=" ")
print()
# Count 1 to 5
print("\nrange(1, 6):")
for i in range(1, 6):
print(i, end=" ")
print()
# Count by 2s
print("\nrange(0, 10, 2):")
for i in range(0, 10, 2):
print(i, end=" ")
print()
# Countdown
print("\nrange(5, 0, -1):")
for i in range(5, 0, -1):
print(i, end=" ")
print("Blast off!")3. The while Loop
The while loop repeats as long as a condition is True. Use it when you don't know exactly how many times to repeat.
# Syntax:
while condition:
code to repeat
update something (important!)
False, or your loop will run forever (infinite loop)!Try It: Basic while Loop
Repeat while a condition is True
# Basic while loop
count = 1
while count <= 5:
print(f"Count is: {count}")
count += 1 # This is crucial! Without it, infinite loop!
print("Loop finished!")
# How it works:
# 1. Check: Is count <= 5? (1 <= 5 = True) → Run code
# 2. Check: Is count <= 5? (2 <= 5 = True) → Run code
# ...continues until...
# 6. Check: Is count <= 5? (6 <= 5 = False) → Exit loop♾️ Infinite Loops and Writing Safe while Loops
An infinite loop runs forever because its condition never becomes False. Your program freezes and you have to force-quit it. Here's how they happen and how to prevent them.
❌ Infinite loop — condition never changes:
count = 1
while count <= 5:
print(count)
# ← Forgot count += 1 !
# count is always 1
# 1 <= 5 is always True
# → Runs forever✅ Safe while loop — guaranteed to exit:
count = 1
while count <= 5:
print(count)
count += 1 # ← Update the variable!
# count grows each iteration
# Eventually 6 <= 5 → False
# → Loop exits cleanlyThe sentinel value pattern — loop until a special value
A sentinel is a special value that signals "stop". This pattern is everywhere in real programs:
# Keep asking until user types "quit"
responses = ["hello", "how are you", "quit"] # Simulates user input
index = 0
while True: # Intentional infinite loop...
user_input = responses[index]
index += 1
if user_input == "quit": # ...with a guaranteed exit
print("Goodbye!")
break
print(f"You said: {user_input}")while True: is valid — an intentional infinite loop is fine as long as you have a break condition inside. This pattern is used for menus, game loops, and server request handling.
Safety net: maximum iteration counter
MAX_TRIES = 1000
tries = 0
while some_condition and tries < MAX_TRIES:
# ... do work ...
tries += 1
if tries >= MAX_TRIES:
print("Warning: hit maximum iterations — check your logic!")When writing complex while loops, adding a maximum counter is a professional safety habit — it turns an accidental infinite loop into a detectable bug.
4. When to Use for vs while
| Use for | Use while |
|---|---|
| You know how many times to repeat | You don't know when to stop |
| Looping through a list/string | Waiting for user input |
| "Do this 10 times" | "Keep going until X happens" |
| for i in range(10): | while not done: |
Quick Rule:
If you can answer "how many times?" → use for
If you can answer "until what?" → use while
🧰 Loop Patterns: The Essential Toolkit
Five patterns appear in virtually every program that uses loops. Learn to recognise them and you'll be able to solve most loop problems from memory.
Pattern 1: Accumulator — build a running total
scores = [85, 92, 78, 96, 73]
total = 0 # ← Start at zero
for score in scores:
total += score # ← Add each item
average = total / len(scores)
print(f"Total: {total}, Average: {average:.1f}") # Total: 424, Average: 84.8Pattern 2: Counter — count items that match a condition
words = ["python", "java", "python", "rust", "python", "go"]
python_count = 0 # ← Start at zero
for word in words:
if word == "python":
python_count += 1
print(f"'python' appears {python_count} times") # 3 timesPattern 3: Filter — collect items that meet a condition
numbers = [3, -1, 7, -4, 0, 9, -2, 5]
positives = [] # ← Start with empty result
for num in numbers:
if num > 0:
positives.append(num) # ← Add matching items
print(f"Positives: {positives}") # [3, 7, 9, 5]Pattern 4: Maximum/Minimum finder
temperatures = [18.5, 22.1, 15.3, 25.8, 19.0, 12.4]
highest = temperatures[0] # ← Assume first is the answer
for temp in temperatures:
if temp > highest:
highest = temp # ← Update if we find better
print(f"Hottest day: {highest}°C") # 25.8°C
# Python's built-in does the same:
print(f"Using max(): {max(temperatures)}°C")Pattern 5: Transform — build a new list from an old one
names = ["alice", "bob", "charlie"]
capitalised = []
for name in names:
capitalised.append(name.capitalize())
print(capitalised) # ['Alice', 'Bob', 'Charlie']You'll soon learn a shorter way to write this using list comprehensions — but the pattern is the same.
5. Loop Control: break and continue
Sometimes you need more control over your loops. Python provides two special keywords:
break
Exit the loop immediately
Like hitting the emergency stop button
continue
Skip to the next iteration
Like saying "skip this one, move on"
Try It: break and continue
Control loop flow with break and continue
# break - exit the loop early
print("Using break:")
for i in range(10):
if i == 5:
print("Found 5! Stopping.")
break
print(i)
print("\n" + "="*30 + "\n")
# continue - skip current iteration
print("Using continue (skip even numbers):")
for i in range(10):
if i % 2 == 0: # If even
continue # Skip to next iteration
print(i) # Only prints odd numbers🔀 The else Clause on Loops — Python's Hidden Feature
Python has a feature almost no other language has: an else block on loops. It sounds confusing at first, but it solves a real problem elegantly.
The rule:
The else block runs only if the loop completed without hitting a break. If break was triggered, else is skipped entirely.
Without for/else (old way):
names = ["Alice", "Bob", "Charlie"]
search = "Diana"
found = False # Need a flag variable
for name in names:
if name == search:
print("Found!")
found = True
break
if not found: # Check the flag
print("Not found")With for/else (Pythonic way):
names = ["Alice", "Bob", "Charlie"]
search = "Diana"
for name in names:
if name == search:
print("Found!")
break
else: # Runs if no break hit
print("Not found")
# No flag variable needed!Real use case: searching for a prime number factor
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
print(f"{n} is divisible by {i} — not prime")
break
else:
print(f"{n} is prime!") # Only runs if no factor was found
return True
return False
is_prime(17) # 17 is prime!
is_prime(15) # 15 is divisible by 3 — not primefor/else pattern eliminates the need for a "found" flag variable. If you find yourself writing found = False before a loop and if not found: after it — that's a signal to use for/else instead.6. Looping Through Different Data Types
You can loop through many types of sequences in Python:
| Data Type | What You Get Each Iteration |
|---|---|
| List | Each item in the list |
| String | Each character |
| Dictionary | Each key (or use .items() for key-value pairs) |
| range() | Each number in the sequence |
Try It: Looping Through Data Types
Loop through strings, dictionaries, and more
# Loop through a string
print("Characters in 'Hello':")
for char in "Hello":
print(char, end=" ")
print()
# Loop through a dictionary
print("\nPerson info:")
person = {"name": "Alice", "age": 25, "city": "Paris"}
for key, value in person.items():
print(f" {key}: {value}")
# Use enumerate() to get index + value
print("\nWith index:")
colors = ["red", "green", "blue"]
for i, color in enumerate(colors):
print(f" {i}: {color}")🔧 Loop Helpers: enumerate(), zip(), and reversed()
Python includes several built-in functions that make loops dramatically more powerful and readable. These are used constantly in real code.
enumerate() — get the index alongside the value
Without it, you'd need a manual counter variable. With it, Python tracks the index for you:
Old way (manual counter):
players = ["Alice", "Bob", "Charlie"]
i = 0
for player in players:
print(f"{i+1}. {player}")
i += 1With enumerate():
players = ["Alice", "Bob", "Charlie"]
for i, player in enumerate(players, start=1):
print(f"{i}. {player}")
# 1. Alice
# 2. Bob
# 3. CharlieThe start=1 argument makes numbering start at 1 instead of 0 — perfect for user-facing lists.
zip() — loop through two sequences in parallel
zip() pairs up items from two (or more) sequences, giving you one item from each per iteration:
names = ["Alice", "Bob", "Charlie"]
scores = [92, 78, 85]
for name, score in zip(names, scores):
grade = "Pass" if score >= 60 else "Fail"
print(f"{name}: {score}/100 — {grade}")
# Output:
# Alice: 92/100 — Pass
# Bob: 78/100 — Pass
# Charlie: 85/100 — Passzip() stops at the shortest sequence. If one list has 3 items and another has 5, you get 3 pairs.
reversed() — loop backwards through a sequence
steps = ["Open app", "Log in", "Browse", "Checkout", "Pay"]
print("Reverse order:")
for step in reversed(steps):
print(f" ← {step}")
# Countdown using reversed() with range:
for i in reversed(range(1, 6)):
print(i, end=" ")
print("Go!") # 5 4 3 2 1 Go!Remember: these are all "iterables"
Lists, strings, range(), enumerate(), zip(), and reversed() are all things Python can loop over. The technical term is iterable. Any time you use for x in ___, the blank must be an iterable.
7. Nested Loops (Loop Inside a Loop)
You can put a loop inside another loop. The inner loop runs completely for each iteration of the outer loop.
How nested loops work:
Outer loop runs once → Inner loop runs completely
Outer loop runs again → Inner loop runs completely again
...and so on
Try It: Nested Loops
Create a multiplication table with nested loops
# Nested loop example - multiplication table
print("3x3 Multiplication Table:")
print("-" * 15)
for i in range(1, 4): # Outer: rows 1, 2, 3
for j in range(1, 4): # Inner: columns 1, 2, 3
result = i * j
print(f"{i}x{j}={result}", end=" ")
print() # New line after each row
# How many times does the inner code run?
# 3 (outer) × 3 (inner) = 9 times⚡ List Comprehensions: The Pythonic Way to Build Lists
A list comprehension is a compact, one-line way to build a list using a loop — and it's one of the most distinctly "Pythonic" features of the language. Once you understand them, you'll use them constantly.
The transformation: for loop → list comprehension
Traditional for loop (4 lines):
numbers = [1, 2, 3, 4, 5]
squared = []
for n in numbers:
squared.append(n ** 2)
# squared = [1, 4, 9, 16, 25]List comprehension (1 line — same result):
numbers = [1, 2, 3, 4, 5] squared = [n ** 2 for n in numbers] # squared = [1, 4, 9, 16, 25]
With a filter condition
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # Only keep even numbers: evens = [n for n in numbers if n % 2 == 0] print(evens) # [2, 4, 6, 8, 10] # Square only the odd numbers: odd_squares = [n ** 2 for n in numbers if n % 2 != 0] print(odd_squares) # [1, 9, 25, 49, 81] # Capitalise names that are longer than 4 letters: names = ["Ali", "Bobby", "Charlie", "Di"] long_names = [name.upper() for name in names if len(name) > 4] print(long_names) # ['BOBBY', 'CHARLIE']
Common Mistakes to Avoid
Forgetting to update the condition in while loops
This causes infinite loops! Always change something inside the loop.
Off-by-one errors with range()
range(5) gives 0-4, not 1-5. Use range(1, 6) for 1-5.
Modifying a list while looping through it
This can cause unexpected behavior. Loop through a copy instead.
Using = instead of == in conditions
while x = 5: is wrong. Use while x == 5:
8. Practical Examples
Example 1: Sum of Numbers
Sum of Numbers
Add up numbers from 1 to 100
# Calculate sum of 1 to 100
total = 0
for num in range(1, 101):
total += num
print(f"Sum of 1 to 100 = {total}")
# Using Python's built-in (faster):
print(f"Using sum(): {sum(range(1, 101))}")Example 2: Find an Item
Search Example
Find an item in a list
# Search for an item in a list
names = ["Alice", "Bob", "Charlie", "Diana"]
search_for = "Charlie"
found = False
for name in names:
if name == search_for:
print(f"Found {search_for}!")
found = True
break
if not found:
print(f"{search_for} not in list.")Example 3: Password Attempts
Password Attempts
Limit login attempts with while loop
# Simulate login attempts
correct_password = "secret123"
max_attempts = 3
attempts = 0
# Simulating different password guesses
guesses = ["wrong", "also_wrong", "secret123"]
while attempts < max_attempts:
guess = guesses[attempts] # Simulate user input
attempts += 1
if guess == correct_password:
print(f"Login successful on attempt {attempts}!")
break
else:
remaining = max_attempts - attempts
print(f"Wrong password. {remaining} attempts left
...Mini-Project: FizzBuzz and Number Analysis
FizzBuzz is the most famous beginner programming challenge — it's used in real job interviews to test basic loop and condition logic. If you can write FizzBuzz, you understand loops.
The rules:
- • Count from 1 to 100
- • If a number is divisible by 3 → print "Fizz"
- • If a number is divisible by 5 → print "Buzz"
- • If divisible by both 3 and 5 → print "FizzBuzz"
- • Otherwise → print the number itself
Classic FizzBuzz — uses: for loop, range(), modulo, if/elif/else
for i in range(1, 101):
if i % 3 == 0 and i % 5 == 0:
print("FizzBuzz")
elif i % 3 == 0:
print("Fizz")
elif i % 5 == 0:
print("Buzz")
else:
print(i)i % 3 == 0 and i % 5 == 0 check must come first — if you check i % 3 == 0 first, multiples of 15 print "Fizz" and never reach "FizzBuzz".Extended version — adds: accumulator, counter, filter patterns
# FizzBuzz with statistics
fizz_count = 0
buzz_count = 0
fizzbuzz_count = 0
number_sum = 0 # Sum of numbers that printed as numbers
for i in range(1, 101):
if i % 15 == 0:
print("FizzBuzz", end=" ")
fizzbuzz_count += 1
elif i % 3 == 0:
print("Fizz", end=" ")
fizz_count += 1
elif i % 5 == 0:
print("Buzz", end=" ")
buzz_count += 1
else:
print(i, end=" ")
number_sum += i
print("
=== Statistics ===")
print(f"Fizz: {fizz_count} times")
print(f"Buzz: {buzz_count} times")
print(f"FizzBuzz: {fizzbuzz_count} times")
print(f"Numbers: {100 - fizz_count - buzz_count - fizzbuzz_count}")
print(f"Sum of plain numbers: {number_sum}")Concepts used in this project:
- ✓for loop + range()
- ✓Modulo operator (%)
- ✓if/elif/else chain
- ✓Accumulator pattern
- ✓Counter pattern
- ✓Condition order matters
Challenge: Can you rewrite the FizzBuzz output using a list comprehension? Hint: you'll need the ternary operator from Lesson 4.
Summary: Quick Reference
| Concept | What It Does | Example |
|---|---|---|
| for | Loop through a sequence | for x in list: |
| while | Loop while condition is True | while x < 10: |
| range() | Generate number sequence | range(1, 10, 2) |
| break | Exit loop immediately | if done: break |
| continue | Skip to next iteration | if skip: continue |
| enumerate() | Get index + value | for i, x in enumerate(list): |
Beginner Track Complete!
Congratulations! You've completed the Python basics. You now know:
- Variables and data types
- Operators and expressions
- Control flow with if/elif/else
- Loops with for and while
Next up: Functions - learn how to organize your code into reusable blocks!
🏆 Beginner Track Complete! You've mastered the fundamentals!
Variables, operators, conditions, and loops — these 5 lessons are the foundation of all programming. Every Python developer in the world uses these exact same tools every single day.
🚀 Up next: Functions — learn to package your code into reusable blocks so you never repeat yourself.
Sign up for free to track which lessons you've completed and get learning reminders.