Skip to main content
Python•Last Updated : 20 Oct 2026
~45 min read

Loops in Python: while and for

Repeating work with while and for loops: range(), accumulator patterns, break and continue, the loop else clause, nested loops, and enumerate() and zip().

Repeating while a condition holds

A loop runs a block of code repeatedly. The while loop is the simplest: it checks its condition, runs the block if the condition is true, then goes back and checks again. When the condition becomes false, the program continues after the loop.

Something inside the block must eventually make the condition false. If nothing does, the loop never ends, an infinite loop. (In a terminal, Ctrl+C stops a runaway program.)

Use while when you do not know in advance how many repetitions you need: keep asking until the input is valid, keep halving until the number reaches 1, keep reading until the file ends.

PythonLoop until a condition changes
1savings = 1000
2years = 0
3while savings < 2000:
4 savings = savings * 1.07
5 years += 1
6print(f"Doubled after {years} years: {savings:.2f}")
7
8countdown = 3
9while countdown > 0:
10 print(countdown)
11 countdown -= 1
12print("Go!")
Output
Doubled after 11 years: 2104.85
3
2
1
Go!

Visiting every item with for

The for loop walks through a sequence (or any other iterable) and runs its block once per item, with the loop variable bound to the current item. It stops by itself after the last item, so there is no condition to get wrong.

Strings, lists, tuples, dictionaries, sets, files and range objects are all iterable. Whenever you think "for each item in ...", write a for loop.

Pythonfor over a list and a string
1languages = ["Python", "SQL", "JavaScript"]
2for language in languages:
3 print("I am learning", language)
4
5for letter in "abc":
6 print(letter.upper(), end=" ")
7print()
Output
I am learning Python
I am learning SQL
I am learning JavaScript
A B C 

Counting with range()

range() produces a sequence of integers without building a list in memory. It takes up to three arguments, just like slicing:

  • range(stop): 0, 1, ..., stop - 1
  • range(start, stop): start, start + 1, ..., stop - 1
  • range(start, stop, step): counts by step, which may be negative

The stop value is never included, so range(5) runs exactly five times and range(1, n + 1) covers 1 to n. list(range(...)) shows the numbers when you want to see them.

PythonThree forms of range
1print(list(range(5)))
2print(list(range(2, 7)))
3print(list(range(0, 20, 5)))
4print(list(range(10, 0, -3)))
5for i in range(3):
6 print("Attempt", i + 1)
Output
[0, 1, 2, 3, 4]
[2, 3, 4, 5, 6]
[0, 5, 10, 15]
[10, 7, 4, 1]
Attempt 1
Attempt 2
Attempt 3

Accumulator patterns

Most loops build up a result step by step. The pattern always has three parts: initialise a variable before the loop, update it inside the loop, use it after the loop.

  • Sum: start at 0, add each item.
  • Count: start at 0, add 1 when an item matches.
  • Maximum / minimum: start with the first item (or None), replace it when you find a better one.
  • Collect: start with an empty list or string, append what you need.

Python has built-ins for the simplest cases (sum, len, max, min), but the manual pattern is what you use whenever the rule is your own.

PythonSum, count, max and collect in one pass
1temperatures = [21, 25, 19, 30, 27, 18]
2total = 0
3hot_days = 0
4warmest = temperatures[0]
5above_20 = []
6for t in temperatures:
7 total += t
8 if t > 25:
9 hot_days += 1
10 if t > warmest:
11 warmest = t
12 if t > 20:
13 above_20.append(t)
14print(f"Average: {total / len(temperatures):.1f}")
15print("Hot days:", hot_days, "Warmest:", warmest)
16print("Above 20:", above_20)
Output
Average: 23.3
Hot days: 2 Warmest: 30
Above 20: [21, 25, 30, 27]

Tracing a loop

Follow the loop below one step at a time. Notice that the for line runs once per item (each time it binds the next value of n), and that the if body only runs for even numbers.

Adding the even numbers from 1 to 5

Step 1 of 15
1total = 0
2for n in range(1, 6):
3 if n % 2 == 0:
4 total += n
5print(total)
StepntotalState Evolution
1—0The accumulator total starts at 0.

break and continue

Two statements change a loop's flow from inside:

  • break leaves the loop immediately; the program continues after it. Use it to stop searching once you have found what you need.
  • continue skips the rest of the current iteration and moves on to the next item. Use it to skip items that do not apply, which keeps the main logic unindented.

A while True: loop with a break inside is a common, deliberate pattern when the stopping condition is easiest to check in the middle of the loop.

PythonStop early, skip some
1orders = [120, -5, 80, 0, 300, 45]
2for amount in orders:
3 if amount <= 0:
4 continue
5 if amount > 250:
6 print("Large order found:", amount)
7 break
8 print("Processing", amount)
9
10n = 1
11while True:
12 n *= 3
13 if n > 100:
14 break
15print("First power of 3 above 100:", n)
Output
Processing 120
Processing 80
Large order found: 300
First power of 3 above 100: 243

The loop else clause

A for or while loop may have an else block. It runs when the loop finishes normally, that is, without hitting break. That makes it a clean way to express "searched everything and did not find it" without a separate flag variable.

Note

Read the loop else as "no break". If that reading would confuse your team, a boolean flag such as found = False is a perfectly good alternative.

PythonPrime test with for ... else
1for candidate in [21, 23]:
2 for d in range(2, candidate):
3 if candidate % d == 0:
4 print(candidate, "is divisible by", d)
5 break
6 else:
7 print(candidate, "is prime")
Output
21 is divisible by 3
23 is prime

Nested loops

A loop inside a loop runs the inner loop completely for each iteration of the outer one. Nested loops are natural for grids, tables and comparing every item with every other item.

The work multiplies: an outer loop of 100 and an inner loop of 100 run the inner block 10,000 times. That is fine for small data, and the reason to look for a smarter approach when inputs get large.

PythonA multiplication table and a star pattern
1for row in range(1, 4):
2 line = ""
3 for col in range(1, 5):
4 line += f"{row * col:4}"
5 print(line)
6
7size = 4
8for i in range(1, size + 1):
9 print("*" * i)
Output
   1   2   3   4
   2   4   6   8
   3   6   9  12
*
**
***
****

enumerate() and zip()

Two built-ins remove most of the need for index arithmetic:

  • enumerate(items) gives (index, item) pairs, so you get the position without range(len(items)). Pass start=1 for human-friendly numbering.
  • zip(a, b) walks two (or more) sequences in step, giving one item from each per iteration. It stops at the end of the shortest sequence.

Both work with tuple unpacking in the for line: for i, name in enumerate(names):.

PythonPositions and parallel lists
1names = ["Ada", "Grace", "Linus"]
2scores = [91, 88, 79]
3for position, name in enumerate(names, start=1):
4 print(position, name)
5for name, score in zip(names, scores):
6 print(f"{name:<6}{score:>4}")
Output
1 Ada
2 Grace
3 Linus
Ada     91
Grace   88
Linus   79

Choosing the right loop

A simple rule covers nearly every case: if you are processing each item of a collection or repeating a known number of times, use for. If you are repeating until something happens and cannot predict when, use while.

Best Practices (Do)
  • ✓Iterate directly over items: for name in names.
  • ✓Use enumerate when you also need the index.
  • ✓Make sure every while loop changes something its condition depends on.
  • ✓Give the loop variable a singular name of what it holds: for order in orders.
Common Pitfalls (Don't)
  • ✕Write for i in range(len(items)) just to read items[i].
  • ✕Add or remove items of a list while looping over that same list.
  • ✕Use while with a manual counter where for ... in range() says it directly.
Key Takeaways & Summary
  • •for visits each item of an iterable; while repeats until its condition is false.
  • •range(start, stop, step) never includes stop.
  • •Initialise accumulators before the loop and use them after it.
  • •break stops a loop, continue skips to the next iteration, and the loop's else runs only if there was no break.

Check your understanding

Suggested Quiz
Question 1 of 5

How many times does `for i in range(2, 10, 3):` run its body?

Practice

Loop practice in rising difficulty: digit sums with while, the Collatz sequence, FizzBuzz with a prime twist, nested-loop patterns, and run-length encoding.

[Problem]

Sum of Digits

Reveal Solution & Analysis
Model Solution
[Problem]

Collatz Steps

Reveal Solution & Analysis
Model Solution
[Problem]

FizzBuzz with a Twist

Reveal Solution & Analysis
Model Solution
[Problem]

Pattern Printing with Nested Loops

Reveal Solution & Analysis
Model Solution
[Problem]

Run-Length Encoding

Reveal Solution & Analysis
Model Solution

Quick Syntax & Reference Sheet

Concept / RuleSyntax / Usage
Loop over itemsfor item in items:
Loop n timesfor i in range(n):
Index and itemfor i, item in enumerate(items, start=1):
Two lists in stepfor a, b in zip(xs, ys):
Repeat until donewhile not done:
Stop / skipbreak / continue
Searched and not foundfor ...: ... break else: not_found()

Common Pitfalls & Developer Mistakes

✕ Mistake 1:

Off-by-one with range

Why it happens: range(1, 10) stops at 9.

Correction: Use range(1, n + 1) to include n.
✕ Mistake 2:

A while loop that never ends

Why it happens: Nothing in the body changes the variables in the condition.

Correction: Update the loop variable in every path through the body, or break explicitly.
✕ Mistake 3:

Resetting the accumulator inside the loop

Why it happens: total = 0 inside the loop throws away the previous iterations each time.

Correction: Initialise accumulators once, before the loop.
✕ Mistake 4:

Modifying a list while iterating over it

Why it happens: Removing items shifts the remaining ones, so some are skipped.

Correction: Build a new list (for example with a comprehension) or loop over a copy: for x in items[:].

Frequently Asked Questions

Is there a do-while loop in Python?

No. Use while True: with the body first and an if ...: break at the end, which runs the body at least once.

Why should I avoid range(len(items))?

for item in items is shorter and cannot go out of range. When you need the index too, enumerate(items) gives both.

Can I use the loop variable after the loop?

Yes, it keeps its last value. If the loop never ran, though, the variable may not exist, so do not rely on it unless you initialised it first.

Hands-On Practice Problems

Article Tags:#Python#Loops#for#while#range#Iteration
Was this lesson clear and helpful?

Discussion (0)

Sign in to ask questions and reply.
Loading discussion…
Discuss in community