Loops: For and While
Reviewed & published by Brayan K
A loop in Python is a control structure that repeats a block of code multiple times, using a for loop to iterate over a sequence or a while loop to repeat as long as a condition stays true.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
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.
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:
Use when you know how many times to repeat
"Do this 10 times" or "Do this for each item"
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)① 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).
for variable in sequence:
| 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 |
# 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"
# ✅ Expected output:
# I like apple!
# I like banana!
# I like cherry!
# Done with fruits!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 |
# 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!")
# ✅ Expected output:
# range(5):
# 0 1 2 3 4
#
# range(1, 6):
# 1 2 3 4 5
#
# range(0, 10, 2):
# 0 2 4 6 8
#
# range(5, 0, -1):
# 5 4 3 2 1 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.
# 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
# ✅ Expected output:
# Count is: 1
# Count is: 2
# Count is: 3
# Count is: 4
# Count is: 5
# Loop finished!♾️ 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: |
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:
Exit the loop immediately
Like hitting the emergency stop button
Skip to the next iteration
Like saying "skip this one, move on"
# 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
# ✅ Expected output:
# Using break:
# 0
# 1
# 2
# 3
# 4
# Found 5! Stopping.
#
# ==============================
#
# Using continue (skip even numbers):
# 1
# 3
# 5
# 7
# 9🔀 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 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 prime6. 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 |
# 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}")
# ✅ Expected output:
# Characters in 'Hello':
# H e l l o
#
# Person info:
# name: Alice
# age: 25
# city: Paris
#
# With index:
# 0: red
# 1: green
# 2: blue🔧 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 += 1players = ["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
# 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
# ✅ Expected output:
# 3x3 Multiplication Table:
# ---------------
# 1x1=1 1x2=2 1x3=3
# 2x1=2 2x2=4 2x3=6
# 3x1=3 3x2=6 3x3=9⚡ 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
# 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))}")
# ✅ Expected output:
# Sum of 1 to 100 = 5050
# Using sum(): 5050Example 2: Find an Item
# 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.")
# ✅ Expected output:
# Found Charlie!Example 3: Password Attempts
# 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.")
else:
print("Account locked!")
# ✅ Expected output:
# Wrong password. 2 attempts left.
# Wrong password. 1 attempts left.
# Login successful on attempt 3!# 🎯 YOUR TURN — replace each ___ using the hint beside it.
prices = [4.50, 0.00, 12.99, 3.20, 0.00, 25.00, 7.75]
card_cap = 40.00
total = 0.0
scanned = 0
# 1) You want the position AND the value, so wrap the list in this.
for i, price in ___(prices): # 👉 replace ___ with enumerate
# 2) A voided line is 0.00 — skip to the next turn of the loop.
if price == 0.00:
___ # 👉 replace ___ with continue
# 3) Adding this one would pass the cap, so leave the loop entirely.
if total + price > card_cap:
print(f"Line {i} would pass the cap - stopping")
___ # 👉 replace ___ with break
total += price
scanned += 1
print("Items rung up:", scanned)
print(f"Total: {total:.2f}")
# 4) Count DOWN from 3 to 1: start, stop-before, step.
for countdown in ___(3, 0, -1): # 👉 replace ___ with range
print("Printing receipt in", countdown)
names = ["ada", "ben", "cara"]
# 5) One output per input, written on one line.
shouted = [n.upper() ___ n in names] # 👉 replace ___ with for
print("Shouted:", shouted)
# A for/else: else runs only when the loop was never broken out of.
for name in names:
if name.startswith("z"):
break
else:
print("No name started with z")
# ✅ Expected output:
# Line 5 would pass the cap - stopping
# Items rung up: 3
# Total: 20.69
# Printing receipt in 3
# Printing receipt in 2
# Printing receipt in 1
# Shouted: ['ADA', 'BEN', 'CARA']
# No name started with zMini-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.
- • 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)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("\n\n=== 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 the Control Flow lesson.
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
🏆 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.
Practice quiz
Which loop is best when you know exactly how many times to repeat?
- while loop
- do-while loop
- for loop
- repeat loop
Answer: for loop. A for loop is used when you know how many times (or which items) to iterate over.
What numbers does range(5) produce?
- 0, 1, 2, 3, 4
- 1, 2, 3, 4, 5
- 0, 1, 2, 3, 4, 5
- 5
Answer: 0, 1, 2, 3, 4. range(5) goes from 0 to 4 — the stop value is NOT included.
What does range(2, 6) produce?
- 2, 3, 4, 5, 6
- 2, 6
- 0, 1, 2, 3, 4, 5
- 2, 3, 4, 5
Answer: 2, 3, 4, 5. range(start, stop) gives start up to stop-1: 2, 3, 4, 5.
What does range(0, 10, 2) produce?
- 0, 2, 4, 6, 8, 10
- 0, 2, 4, 6, 8
- 0, 1, 2, ..., 10
- 2, 4, 6, 8
Answer: 0, 2, 4, 6, 8. The step of 2 yields even numbers from 0 up to (but not including) 10.
What does the 'break' keyword do inside a loop?
- Exits the loop immediately
- Skips the current iteration
- Restarts the loop
- Pauses the loop
Answer: Exits the loop immediately. break exits the loop immediately, skipping any remaining iterations.
What does the 'continue' keyword do?
- Exits the loop
- Ends the program
- Skips to the next iteration
- Repeats the current item
Answer: Skips to the next iteration. continue skips the rest of the current iteration and moves to the next one.
What causes an infinite while loop?
- Using range()
- The condition never becoming False
- Using break
- Too many items
Answer: The condition never becoming False. If the while condition never becomes False (e.g. you forget to update the variable), it runs forever.
Which loop should you use to 'keep asking until the user types quit'?
- for loop
- range loop
- nested loop
- while loop
Answer: while loop. A while loop repeats until a condition changes — ideal when you don't know how many iterations.
After 'for fruit in ["a", "b", "c"]:' finishes, what value does fruit hold?
- 'a'
- 'c'
- None
- It no longer exists
Answer: 'c'. The loop variable keeps the last value it took, 'c', after the loop ends.
Is 'while True:' with a break inside considered valid Python?
- No, it always errors
- Only in functions
- Yes, an intentional infinite loop with a break exit is fine
- Only with range()
Answer: Yes, an intentional infinite loop with a break exit is fine. while True: is valid as long as a break (or return) eventually exits it.
Continue this course
- Previous: Control Flow - If/Else
- Next: Functions — Write reusable blocks of code and pass data in and out with parameters
- Quick reference: Python cheat sheet › Loops & Iteration
- From the blog: The Two Things That Actually Confused Me Learning Python (That No Course Explains)