Skip to content

Loops — for, while, break, continue

Loops let you repeat code instead of writing it many times.

The while loop

Repeats while a condition is True.

count = 1
while count <= 5:
    print(f"Count: {count}")
    count += 1     # CRUCIAL — otherwise infinite loop

print("Done")

Always change something each iteration that eventually makes the condition False. Otherwise you have an infinite loop.

The for loop

Iterates over a sequence (list, string, range, dict, etc.).

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

Loop over a string — character by character:

for letter in "Python":
    print(letter)

Loop a specific number of times with range():

# range(5) → 0, 1, 2, 3, 4
for i in range(5):
    print(i)

range(start, stop, step):

for i in range(1, 11):        # 1 to 10
    print(i, end=" ")
print()

for i in range(0, 20, 2):     # even numbers 0 to 18
    print(i, end=" ")
print()

for i in range(10, 0, -1):    # 10 down to 1
    print(i, end=" ")

enumerate — get index + value

fruits = ["apple", "banana", "cherry"]
for i, fruit in enumerate(fruits):
    print(f"{i}: {fruit}")

zip — loop over two lists in parallel

names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]

for name, age in zip(names, ages):
    print(f"{name} is {age}")

Nested loops

A loop inside a loop. The inner loop runs completely for each iteration of the outer.

# Multiplication table
for i in range(1, 4):
    for j in range(1, 4):
        print(f"{i} x {j} = {i*j}", end="\t")
    print()        # newline after each row

Watch out: a nested loop with N×M iterations can be slow. 1000 × 1000 = 1,000,000 iterations.

break — exit the loop early

for i in range(10):
    if i == 5:
        break       # jump out of the loop
    print(i)

print("After loop")

continue — skip the rest of this iteration

# Print only odd numbers
for i in range(10):
    if i % 2 == 0:
        continue    # skip the print, go to next iteration
    print(i)

pass — placeholder that does nothing

Useful while writing skeleton code:

for i in range(3):
    pass    # TODO: fill in later

print("Loop ran but did nothing")

for / while with else

The else block runs only if the loop finished normally (no break):

# Find first even number
for num in [1, 3, 5, 7, 8, 9]:
    if num % 2 == 0:
        print(f"Found even: {num}")
        break
else:
    print("No even number found")

Try removing 8 from the list and re-run.

Mini-project — Number Guessing Game

import random

secret = random.randint(1, 10)
guesses = [3, 7, 5]    # simulated guesses since input() is interactive

for attempt, guess in enumerate(guesses, 1):
    print(f"Attempt {attempt}: guessing {guess}")
    if guess == secret:
        print(f"🎉 Correct! It was {secret}")
        break
    elif guess < secret:
        print("Too low")
    else:
        print("Too high")
else:
    print(f"Out of attempts. Secret was {secret}")

Common pitfalls

  • Infinite loop — forgetting to update the condition in while.
  • Modifying a list while iterating over it — leads to skipped elements. Iterate over a copy: for x in items[:]: or items.copy().
  • Using for i in range(len(items)) when you don't need the index — for item in items is more Pythonic.

Predict the output

What does this loop print?

Expected: 0 1 2

for i in range(5):
    if i == 3:
        break
    print(i, end=" ")

Fix the bug

The author wanted the squares of 1 through 5, but the output is wrong. Edit the code until it matches expected.

Print the squares 1 to 5

Expected: 1 4 9 16 25

for i in range(1, 6):
    print(i * 2, end=" ")   # bug: should be i ** 2

Quiz — Quick check

What you remember

Q1. Which keyword exits a loop immediately?

  • continue
  • break
  • pass
  • return

Why: break jumps out of the enclosing loop. continue only skips to the next iteration.

Q2. What does range(1, 10, 2) produce?

  • 1, 2, 3, …, 10
  • 1, 3, 5, 7, 9
  • 2, 4, 6, 8, 10
  • 1, 3, 5, 7, 9, 11

Why: range(start, stop, step) is half-open on stop. Start at 1, step by 2, stop before 10.

Q3. A for / else clause runs when…

  • the loop body raises an exception
  • the loop body is empty
  • the loop finishes without hitting break
  • always

Why: The else of a loop is the "no-break" branch — runs only if the loop completed normally.

Common doubts

Why use for item in items instead of for i in range(len(items))?

The first form gives you the item directly, which is what you usually want. Use enumerate(items) when you need both index and value. range(len(items)) is a Java/C habit — Python doesn't need it.

What's the difference between break and return?

break exits the loop and continues with the code after it. return exits the entire function and sends back a value. If you're inside a function and want to bail out completely, return is shorter than break followed by more logic.

Is while True bad?

Not at all — it's the idiomatic way to write a loop that needs a break somewhere inside (e.g. event loops, retry loops). The pitfall is forgetting the break and creating an infinite loop.

What's next

Functions