Python Loops Made Easy: For, While, and When to Use Each
A clear, beginner-friendly explanation of for loops and while loops in Python, with common mistakes to avoid.
By Adegbite Olaoluwa, Founder & Developer, StudiByte · Last updated
A loop lets you repeat a block of code without writing it out multiple times. Python has two loop types: for loops, which repeat a fixed number of times or over a known sequence, and while loops, which repeat as long as a condition stays true.
This guide walks through both, shows when each is the right tool, and covers the mistakes that trip up most first-year students. Every example is short enough to type out and run yourself, which is the best way to learn them.
The for loop
Use a for loop when you know what you're iterating over — a list of students, a range of numbers, the characters in a string. Example: for student in students: print(student) runs once per item in the list, in order, and stops automatically when the list is exhausted.
students = ["Ada", "Tunde", "Chioma"]
for student in students:
print(student)On each pass, the variable student takes the next value from the list. You can loop over almost any collection this way, including strings, where each character is one item:
for char in "code":
print(char)Counting with range()
range(n) is commonly paired with for when you need a fixed count rather than an existing list: for i in range(5): print(i) prints 0 through 4. A frequent beginner mistake is expecting range(5) to include 5 — it doesn't; it stops one before the given number.
range accepts up to three arguments: where to start, where to stop (not included), and the step size.
for i in range(5):
print(i) # 0 1 2 3 4
for i in range(1, 6):
print(i) # 1 2 3 4 5
for i in range(0, 10, 2):
print(i) # 0 2 4 6 8When you need both the position and the value, use enumerate instead of managing a counter yourself:
scores = [72, 65, 88]
for position, score in enumerate(scores, start=1):
print(position, score)Building a result: the accumulator pattern
Many loops exist to build up a single answer. You create a variable before the loop, update it inside the loop, and use it afterwards. This is called an accumulator.
scores = [72, 65, 88]
total = 0
for score in scores:
total += score
average = total / len(scores)
print(average) # 75.0A common bug is creating the accumulator inside the loop, which resets it to zero on every pass. Put the starting value before the loop.
The while loop
Use a while loop when you don't know in advance how many repetitions you need — only the condition that should stop it. Example: while attempts < 3: attempts += 1 keeps running until the condition becomes false. The most common bug here is forgetting to update the variable inside the loop (like attempts += 1), which creates an infinite loop that never stops.
attempts = 0
while attempts < 3:
attempts += 1
print("Attempt", attempts)A more realistic case is one where the number of repetitions depends on the data. How many months does it take for savings of 1000 to reach 1500 at 5% growth per month?
balance = 1000
months = 0
while balance < 1500:
balance *= 1.05
months += 1
print(months) # 9You could not write that as a for loop without already knowing the answer. That is the sign that while is the right tool.
Choosing between them
A good rule of thumb: if you can say "for each item in this collection," reach for for. If you can only say "keep going until this becomes true," reach for while.
- "Print every student's name" →
for - "Add up all the scores in a list" →
for - "Repeat 10 times" →
forwithrange(10) - "Keep asking until the user types a valid number" →
while - "Keep halving the number until it is below 1" →
while
Controlling a loop: break, continue and else
break exits a loop immediately, useful when you find what you're looking for and don't need to keep checking. continue skips the rest of the current iteration and moves to the next one, useful for skipping items that don't meet a condition without exiting the whole loop.
names = ["Ada", "Tunde", "Chioma", "Emeka"]
for name in names:
if name == "Chioma":
print("Found her")
break
for n in range(1, 8):
if n % 2 == 0:
continue
print(n) # 1 3 5 7Python also lets a loop have an else block, which runs only if the loop finished without hitting break. It is handy for "search, and do something if nothing was found":
for n in range(2, 10):
if n == 7:
print("found 7")
break
else:
print("not found")Loops inside loops
You can place one loop inside another. The inner loop runs completely for every single pass of the outer loop. A multiplication table is the classic example:
for row in range(1, 4):
for col in range(1, 4):
print(row * col, end=" ")
print()This prints three rows of three numbers. If the outer loop runs 3 times and the inner loop runs 3 times, the body runs 9 times in total. Nested loops get slow quickly as the numbers grow, so keep an eye on how many times the innermost line actually runs.
Common mistakes to avoid
Infinite loops. The loop condition never becomes false because the variable is never updated:
count = 0
while count < 3:
print(count)
# forgot count += 1, so this never stopsIf this happens in a terminal, press Ctrl+C to stop the program, then fix the update line.
Off-by-one errors. range(5) gives 0 to 4, and range(1, 5) gives 1 to 4. When your output has one item too many or too few, check the start and stop values first.
Changing a list while looping over it. Removing items from a list during a for loop shifts the remaining items and makes the loop skip some of them:
nums = [2, 4, 6, 7]
for n in nums:
if n % 2 == 0:
nums.remove(n)
print(nums) # [4, 7] (4 should have been removed)Build a new list instead:
nums = [2, 4, 6, 7]
odd_only = [n for n in nums if n % 2 != 0]
print(odd_only) # [7]Using range(len(x)) when you do not need the index. Looping directly over the items is shorter and harder to get wrong. Reach for range(len(x)) only when you genuinely need the position, and even then enumerate is usually cleaner.
Practice exercises
Try each one on your own before reading the answer, because that struggle is where the learning happens.
- Add up the numbers from 1 to 100.
- Count the vowels in a word.
- Print the numbers 1 to 15, but print "Fizz" for multiples of 3, "Buzz" for multiples of 5, and "FizzBuzz" for multiples of both.
- Simulate a guessing game that keeps checking guesses from a list until it finds the secret number, and report how many guesses it took.
Possible solutions:
# 1. Sum from 1 to 100
total = 0
for n in range(1, 101):
total += n
print(total) # 5050
# 2. Count vowels
def count_vowels(text):
count = 0
for ch in text.lower():
if ch in "aeiou":
count += 1
return count
print(count_vowels("Programming")) # 3
# 3. FizzBuzz
for i in range(1, 16):
if i % 15 == 0:
print("FizzBuzz")
elif i % 3 == 0:
print("Fizz")
elif i % 5 == 0:
print("Buzz")
else:
print(i)
# 4. Guessing game
guesses = [50, 25, 37, 42]
secret = 42
tries = 0
while tries < len(guesses):
guess = guesses[tries]
tries += 1
if guess == secret:
break
print(tries) # 4Notice that FizzBuzz checks the multiple of 15 first. If you check 3 or 5 first, the "FizzBuzz" case is never reached. Order matters in an if/elif chain, which is a very common exam question.
How to practise from here
Reading about loops only gets you part of the way. Type every example instead of copying it, change a number, and predict what will happen before you run it. When you can write all four exercises above from a blank page, you understand loops well enough for most first-year programming exams.