Python: Zero to Hero
Home/The Foundation
Share

Chapter 5: Repeating Things — Loops

At the end of Chapter 4 you built a number guessing game. The user guesses once, gets feedback, and the program ends. But a real guessing game lets you keep trying until you get it right.

That's what loops do. A loop runs a block of code again and again — as many times as you need. Without loops, you'd have to copy and paste the same code dozens of times. With loops, you write it once and let Python repeat it.

This is one of the most important ideas in all of programming. Let's dig in.

Why Loops Exist

Imagine printing every number from 1 to 100. Without a loop:

print(1)
print(2)
print(3)
# ... 97 more lines
print(100)

That's 100 lines of nearly identical code. Now with a loop:

for i in range(1, 101):
    print(i)

Two lines. Same result. That's the power of loops.

But loops aren't just for counting. They're for processing every item in a list, reading every line in a file, repeating a question until you get a valid answer, and a thousand other patterns you'll use every day.

Python has two kinds of loops: for and while. You'll use both.

for Loops — Repeating a Known Number of Times

A for loop goes through a sequence — a range of numbers, a list, a string, anything you can iterate over — and runs the indented block once for each item.

for i in [1, 2, 3, 4, 5]:
    print(i)

Output:

1
2
3
4
5

The variable i takes each value from the list in turn. First it's 1, the block runs. Then it's 2, the block runs. And so on until the list is exhausted.

The variable name i is just a convention for "index" or "iteration." You can call it anything.

for number in [10, 20, 30]:
    print(f"The number is {number}")

Output:

The number is 10
The number is 20
The number is 30

Your turn: Write a for loop that prints these three words, one per line: "Python", "is", "fun".

range() — Generating Sequences of Numbers

Typing out a list like [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] is tedious. range() generates a sequence of numbers on demand, without storing them all in memory.

range(stop) — Start at 0, count up to (but not including) stop

for i in range(5):
    print(i)

Output:

0
1
2
3
4

range(5) gives you 0, 1, 2, 3, 4. It stops before 5. This trips up beginners constantly — remember: the stop value is excluded.

range(start, stop) — Control where you start

for i in range(1, 6):
    print(i)

Output:

1
2
3
4
5

Now it starts at 1 and stops before 6. Much more natural for counting things humans care about.

range(start, stop, step) — Control the step size

for i in range(0, 11, 2):
    print(i)

Output:

0
2
4
6
8
10

The step is 2, so we jump by 2 each time. You can use any step, including negative — which lets you count backwards.

for i in range(10, 0, -1):
    print(i)
print("Blastoff!")

Output:

10
9
8
7
6
5
4
3
2
1
Blastoff!

Your turn: Use range() to:

  1. Print all odd numbers from 1 to 19.
  2. Print a countdown from 20 to 0, stepping by 5 (20, 15, 10, 5, 0).

Doing Real Work Inside a Loop

The real power of loops is doing something useful on each iteration — not just printing a counter.

Summing numbers

total = 0

for number in range(1, 11):
    total = total + number

print(f"Sum of 1 to 10 is: {total}")

Output:

Sum of 1 to 10 is: 55

Before the loop, total is 0. On each pass, we add the current number to total. After the loop, total holds the sum of everything.

Multiplication table

n = 7

for i in range(1, 11):
    print(f"{n} x {i} = {n * i}")

Output:

7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70

Looping over a string

Strings are sequences too. You can loop over every character.

for letter in "Python":
    print(letter)

Output:

P
y
t
h
o
n

Your turn: Write a loop that calculates and prints the factorial of a number. (Factorial of 5 = 1 x 2 x 3 x 4 x 5 = 120.) Start with result = 1 and multiply on each iteration.

while Loops — Repeating Until a Condition Changes

A while loop keeps running as long as its condition is True. You use it when you don't know in advance how many times you'll need to repeat — you just know when to stop.

count = 0

while count < 5:
    print(f"count is {count}")
    count += 1

Output:

count is 0
count is 1
count is 2
count is 3
count is 4

Python checks the condition before each iteration. If it's True, the block runs. If it's False, the loop ends. Here, once count reaches 5, count < 5 becomes False and we stop.

The critical rule: Something inside the loop must eventually make the condition False. Here count += 1 does that. Without it, count would never change, the condition would stay True forever, and you'd have an infinite loop.

Waiting for valid input

This is the classic use case for while — keep asking until the user gives you what you need.

age = -1

while age < 0:
    age = int(input("Enter your age (must be 0 or more): "))
    if age < 0:
        print("That's not a valid age. Try again.")

print(f"Your age is {age}.")

Sample run:

Enter your age (must be 0 or more): -5
That's not a valid age. Try again.
Enter your age (must be 0 or more): -1
That's not a valid age. Try again.
Enter your age (must be 0 or more): 28
Your age is 28.

The program will not move on until the user gives a non-negative number. This pattern — validate input in a loop — is everywhere in real software.

Your turn: Write a while loop that keeps asking the user to enter a password until they type the correct one ("opensesame"). When they get it right, print "Access granted!"

Infinite Loops and How to Avoid Them

An infinite loop runs forever because its condition never becomes False.

# DANGER — this runs forever
while True:
    print("This never stops!")

If you run this by accident, press Ctrl+C in the terminal to force-stop it.

But infinite loops aren't always a mistake. Sometimes you want to loop forever and use break to exit at the right moment (more on that below). Many real programs — servers, games, dashboards — run in a loop intentionally: "keep running until the user quits."

while True:
    command = input("Enter command (or 'quit' to exit): ")
    if command == "quit":
        print("Goodbye!")
        break
    print(f"You typed: {command}")

Sample run:

Enter command (or 'quit' to exit): hello
You typed: hello
Enter command (or 'quit' to exit): test
You typed: test
Enter command (or 'quit' to exit): quit
Goodbye!

This pattern — while True with a break to exit — is one of the most useful structures in all of Python.

break — Stop the Loop Early

break exits the loop immediately, no matter where you are in the iteration.

for i in range(10):
    if i == 5:
        break
    print(i)

print("Loop ended.")

Output:

0
1
2
3
4
Loop ended.

When i reaches 5, break fires and the loop ends. The print("Loop ended.") runs because it's outside the loop.

A real example: searching for something in a sequence.

names = ["Alice", "Bob", "Carlos", "Diana", "Eve"]
target = "Carlos"

for name in names:
    print(f"Checking {name}...")
    if name == target:
        print(f"Found {target}!")
        break

Output:

Checking Alice...
Checking Bob...
Checking Carlos...
Found Carlos!

Once we find the target, there's no reason to keep checking. break stops the loop early.

continue — Skip One Iteration

continue skips the rest of the current iteration and jumps straight to the next one. The loop doesn't stop — it just skips this pass.

for i in range(10):
    if i % 2 == 0:
        continue   # skip even numbers
    print(i)

Output:

1
3
5
7
9

When i is even, continue fires and we skip the print. When i is odd, nothing skips the print, so it runs.

Another example: printing only the positive numbers from a mixed list.

numbers = [4, -2, 7, -1, 0, 9, -5, 3]

for n in numbers:
    if n <= 0:
        continue
    print(n)

Output:

4
7
9
3

else on a Loop — The Secret Clause

Python loops have a feature most beginners never learn: an else clause. The else block runs after the loop finishes normally — meaning it does not run if the loop was stopped by a break.

for i in range(5):
    print(i)
else:
    print("Loop finished normally.")

Output:

0
1
2
3
4
Loop finished normally.

Now with a break:

for i in range(5):
    if i == 3:
        break
    print(i)
else:
    print("Loop finished normally.")   # this will NOT print

Output:

0
1
2

The else didn't run because break stopped the loop early.

This is incredibly useful for "search and report if not found" patterns:

names = ["Alice", "Bob", "Diana", "Eve"]
target = "Carlos"

for name in names:
    if name == target:
        print(f"Found {target}!")
        break
else:
    print(f"{target} was not found in the list.")

Output:

Carlos was not found in the list.

Without the else clause, you'd need an extra variable to track whether you found the item. With it, Python handles the logic for you.

for vs while — When to Use Each

Situation Use
You know exactly how many times to repeat for
You're going through a sequence (list, string, range) for
You're repeating until a condition changes while
You're waiting for user input while
You want to loop forever until a break while True

If you can write it cleanly as a for loop, prefer for. It's more readable and harder to accidentally infinite-loop.

Nested Loops

You can put a loop inside another loop. The inner loop runs completely for every single iteration of the outer loop.

for row in range(1, 4):
    for col in range(1, 4):
        print(f"({row},{col})", end="  ")
    print()   # new line after each row

Output:

(1,1)  (1,2)  (1,3)  
(2,1)  (2,2)  (2,3)  
(3,1)  (3,2)  (3,3)  

The end=" " in print() tells Python not to add a newline — just a space — after each item. The plain print() at the end of the outer loop adds the newline to finish each row.

Nested loops are essential for working with grids, tables, and combinations. But be careful: if the outer loop runs 100 times and the inner loop runs 100 times, that's 10,000 total iterations. Nesting goes deep fast.

Your turn: Use nested loops to print a multiplication table from 1x1 to 5x5. Each row should show all five products for that multiplier.

Putting It All Together: The Guessing Game

Remember the guessing game from Chapter 4 that only let you guess once? Here it is, completed with a loop.

import random

secret = random.randint(1, 100)
attempts = 0
max_attempts = 7

print("I'm thinking of a number between 1 and 100.")
print(f"You have {max_attempts} attempts.")

while attempts < max_attempts:
    guess = int(input("Your guess: "))
    attempts += 1

    if guess < secret:
        print(f"Too low! ({max_attempts - attempts} attempts left)")
    elif guess > secret:
        print(f"Too high! ({max_attempts - attempts} attempts left)")
    else:
        print(f"You got it in {attempts} attempt(s)! The number was {secret}.")
        break
else:
    print(f"Out of attempts! The number was {secret}.")

Sample run:

I'm thinking of a number between 1 and 100.
You have 7 attempts.
Your guess: 50
Too high! (6 attempts left)
Your guess: 25
Too low! (5 attempts left)
Your guess: 37
Too low! (4 attempts left)
Your guess: 43
You got it in 4 attempt(s)! The number was 43.

Look at what's happening here:

  • while attempts < max_attempts keeps the loop going until attempts run out
  • break exits the loop when the player wins
  • The else on the while loop runs only if attempts ran out (i.e., break was never hit)
  • random.randint(1, 100) picks a random number — you'll learn more about random in Chapter 16

This is a complete, playable game. Built with tools you now know.

What You Learned in This Chapter

  • for loops iterate over a sequence — a list, a range(), or any iterable.
  • range(stop) starts at 0. range(start, stop) gives you control. range(start, stop, step) lets you skip or count backwards.
  • while loops repeat as long as a condition is True. Use them when you don't know the count in advance.
  • while True with a break is the standard pattern for "loop until done."
  • break exits the loop immediately.
  • continue skips the rest of the current iteration and moves to the next.
  • else on a loop runs after the loop finishes normally — it's skipped if break fired.
  • Nested loops let you work with rows and columns, grids, and combinations.
  • Always make sure a while loop's condition will eventually become False.

What's Next?

Your programs can now repeat. But they're still working with one value at a time — one number, one name, one score.

In Chapter 6 you'll learn about lists — a way to store many values in a single variable. You'll combine lists with loops and suddenly be able to process hundreds of items with just a few lines of code. It's where things start to feel truly powerful.

Your turn: Write a program that asks the user to enter numbers one at a time. After each number, add it to a running total and print the current total. Stop when the user types 0. At the end, print how many numbers they entered and what the total was. (Hint: use while True and break.)

© 2026 Abhilash Sahoo. Python: Zero to Hero.