Loops are one of the first big ideas you learn in Python, and you will use them in almost every program you write. A loop lets you run the same block of code again and again, either a set number of times or until a condition stops being true.
This guide covers everything you need for class and assignments: while loops, for loops, range(), nested loops, break, continue, and pass. It also covers enumerate(), the built-in function that gives you the index and the value together while you loop. Every example has been run, and the output shown is the real output.
TL;DR: Loops And enumerate() In Python
| Topic | Summary |
|---|---|
| What a loop does | Runs a block of code over and over, until a condition is false or there are no items left. |
| while loop | Repeats as long as a condition is true. Best when you do not know how many times it will run. |
| for loop | Goes through each item in a sequence, like a list, a string, or range(). Best when you know what you are looping over. |
| Loop control | break exits the loop, continue skips to the next round, and pass does nothing and acts as a placeholder. |
| enumerate() | Gives you the index and the value together, so you do not have to track the index yourself. |
What Is A Loop In Python?
A loop repeats a block of code. Before each round, Python checks whether it should keep going. If yes, it runs the block again. If no, the loop ends and the program moves on.
Python has two loop keywords: while and for. You will also hear people talk about a "for each" loop. In Python, that is just a regular for loop that goes over the items of a list or string directly. Other languages like Java have separate syntax for it, but Python does not.
One thing to remember: Python uses indentation to know which lines are inside the loop. Every line in the loop body must be indented the same amount. If you are new to this, our guide to Python data types covers indentation and the types you will loop over most.
The While Loop
A while loop checks a condition before every round. As long as the condition is true, the loop keeps running. The moment it becomes false, the loop stops.
Inside the loop, something has to change so that the condition eventually becomes false. If nothing changes, you get an infinite loop that never ends.
Syntax:
while condition:
# code to repeat
Example:
count = 1 # Start value
limit = 5 # End value
while count <= limit:
print("Loop run number", count)
count += 1 # Move toward the end, or the loop never stops
Output:
Loop run number 1 Loop run number 2 Loop run number 3 Loop run number 4 Loop run number 5
How it works:
countstarts at 1, andlimitis 5.- Before each round, Python checks
count <= limit. While that is true, it prints a line. count += 1adds 1 each time. After the fifth round,countis 6, the condition is false, and the loop stops.
If you delete the count += 1 line, count stays at 1 forever and the loop never ends. If you are not sure what += does, see our post on the difference between a = a + b and a += b in Python.
The For Loop And range()
A for loop goes through a sequence one item at a time. When you want to repeat something a set number of times, you pair it with range().
range() can take one, two, or three arguments:
range(stop)counts from 0 up to, but not including,stop.range(start, stop)counts fromstartup to, but not including,stop.range(start, stop, step)counts bystep. A negative step counts down.
The stop value is never included. range(0, 5) gives you 0, 1, 2, 3, 4, not 5. This trips up a lot of beginners. With a for loop, you also do not need to add 1 yourself. range() handles the counting for you.
Example:
for i in range(5): # 0, 1, 2, 3, 4
print(i, end=" ")
print()
for i in range(2, 6): # 2, 3, 4, 5
print(i, end=" ")
print()
for i in range(10, 0, -3): # 10, 7, 4, 1 (counting down by 3)
print(i, end=" ")
print()
Output:
0 1 2 3 4 2 3 4 5 10 7 4 1
The end=" " part tells print() to put a space after each number instead of starting a new line.
Looping Over Strings And Lists
This is the "for each" style. You do not need range() at all. The loop variable picks up each item in the string or list, one at a time. It is the simplest and most common loop in Python.
Syntax:
for item in sequence:
# use item
Example:
word = "Python"
for letter in word:
print(letter, end=" ")
print()
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print("I like", fruit)
Output:
P y t h o n I like apple I like banana I like cherry
The name after for is up to you. Pick one that describes a single item, like letter for a string or fruit for a list of fruits. It makes your code much easier to read. If you also need to know the position of each item, use enumerate(), which is covered below.
Nested Loops
A nested loop is a loop inside another loop. For every single round of the outer loop, the inner loop runs all the way through. You can nest for loops, while loops, or a mix of both.
Example: a small multiplication table.
for row in range(1, 4): # Outer loop: rows 1 to 3
for col in range(1, 4): # Inner loop: columns 1 to 3
print(row * col, end="\t")
print() # New line after each row
Output:
1 2 3 2 4 6 3 6 9
How it works:
- The outer loop picks a row: 1, then 2, then 3.
- For each row, the inner loop goes through columns 1 to 3 and prints
row * col. - After the inner loop finishes,
print()moves to a new line for the next row.
Nested loops are common in pattern-printing and grid problems. Be careful with them on big inputs, though. Two nested loops over a list of n items run n × n times.
Loop Control: break, continue, And pass
These three statements change how a loop runs.
1. break
break ends the loop right away, even if there are items left or the condition is still true.
for i in range(1, 7):
if i == 4:
break # Leave the loop completely
print(i)
print("Loop ended")
Output:
1 2 3 Loop ended
The loop was set to run up to 6, but it stopped as soon as i reached 4.
2. continue
continue skips the rest of the current round and jumps to the next one. The loop keeps going.
for i in range(1, 7):
if i == 4:
continue # Skip this round only
print(i)
Output:
1 2 3 5 6
Only 4 is skipped. Everything else prints.
3. pass
pass does nothing. Python needs at least one line inside a loop, so pass is a placeholder you can use while you are still planning the code.
for i in range(3):
pass # Placeholder: do nothing for now
print("The loop ran, but did nothing")
Output:
The loop ran, but did nothing
Bonus: The else Clause On A Loop
This one surprises many students. A for or while loop can have an else block. It runs only if the loop finished normally, without hitting break. It is handy for search problems.
numbers = [3, 7, 11, 15]
for n in numbers:
if n % 2 == 0:
print("Found an even number:", n)
break
else:
print("No even numbers in the list") # Runs only if the loop did not break
Output:
No even numbers in the list
How To Use enumerate() In Python
enumerate() is a built-in function that lets you loop over a list, string, or any other iterable while getting both the index and the value at the same time. It is one of the most useful tools you can learn for writing clean loops.
Why Indexes Confuse Students
Indexes seem simple at first, but they cause a lot of bugs in assignments and exams. Here is why:
- People count from 1, but Python indexes start at 0. That leads to off-by-one errors.
- With
range(len(my_list)), it is easy to mix up the indexiand the valuemy_list[i]. - Code that hard-codes index logic can break when the list changes size.
- Under exam pressure, students add extra counter variables and make more mistakes.
Here is the "old way" many students write first:
subjects = ["English", "Math", "Science"]
# The old way: range(len()) plus manual indexing
for i in range(len(subjects)):
print(i, subjects[i])
Output:
0 English 1 Math 2 Science
It works, but subjects[i] is extra noise. enumerate() fixes that.
enumerate() Syntax And Basic Use
Syntax:
enumerate(iterable, start=0)
- iterable: the list, string, tuple, dictionary view, or other sequence you want to loop over.
- start: the number to start counting from. It is optional and defaults to 0.
Here is the same loop as above, written with enumerate():
subjects = ["English", "Math", "Science"]
for index, subject in enumerate(subjects):
print(index, subject)
Output:
0 English 1 Math 2 Science
Each round, enumerate() hands back a pair: the index and the value. The line for index, subject in ... unpacks that pair into two variables.
What does enumerate() actually return? It returns an enumerate object, not a list. It produces its pairs one at a time as the loop asks for them. If you want to see all the pairs at once, wrap it in list():
subjects = ["English", "Math", "Science"]
result = enumerate(subjects)
print(result) # An enumerate object, not a list
print(list(enumerate(subjects))) # Convert it to see the pairs
print(list(enumerate(subjects, 100))) # Start counting at 100
Output:
<enumerate object at 0x7f073f825490> [(0, 'English'), (1, 'Math'), (2, 'Science')] [(100, 'English'), (101, 'Math'), (102, 'Science')]
The memory address in the first line (0x...) will be different on your computer. Notice the pairs are tuples, written in parentheses.
Changing The Start Value
Teachers often want numbered output that starts at 1, not 0. Pass start=1:
subjects = ["English", "Math", "Science"]
for number, subject in enumerate(subjects, start=1):
print(f"{number}. {subject}")
Output:
1. English 2. Math 3. Science
start only changes the counter that enumerate() gives you. It does not change the real list indexes. subjects[1] is still "Math".
enumerate() With A String
enumerate() works on strings too, giving you each character and its position:
name = "CodingZap"
for position, char in enumerate(name):
if char.isupper():
print("Capital letter", char, "at index", position)
Output:
Capital letter C at index 0 Capital letter Z at index 6
This is useful for problems like "find the position of every vowel" or "find where the first space is."
Using One Variable Instead Of Two
If you only put one variable after for, you get the whole pair as a tuple:
subjects = ["English", "Math", "Science"]
for pair in enumerate(subjects):
print(pair) # One variable gets the whole (index, value) tuple
Output:
(0, 'English') (1, 'Math') (2, 'Science')
That is why the output has parentheses. Most of the time you want two variables, so you can use the index and value separately.
Using The Index To Change A List
This is where enumerate() really helps. You get the value to check and the index to update the original list:
scores = [72, 45, 88, 39]
# Add 5 bonus points to any score below 50
for i, score in enumerate(scores):
if score < 50:
scores[i] = score + 5 # Use the index to change the original list
print(scores)
Output:
[72, 50, 88, 44]
Note that changing score alone would not update the list. You need scores[i] to change the actual item.
How To Stop enumerate() Early
Sometimes you only want to go up to a certain point. There are two easy ways.
Option 1: Use break when a condition is met.
subjects = ["English", "Math", "Science", "History"]
for index, subject in enumerate(subjects):
if subject == "Science":
break # Stop enumerating here
print(index, subject)
Output:
0 English 1 Math
Option 2: Limit how many items you loop over. You can slice the list first, or use islice() from the itertools module, which works even on things you cannot slice, like a file.
from itertools import islice
subjects = ["English", "Math", "Science", "History"]
# Option 1: slice the list first
for index, subject in enumerate(subjects[:2]):
print(index, subject)
print("---")
# Option 2: islice works on any iterable, even ones you cannot slice
for index, subject in islice(enumerate(subjects), 2):
print(index, subject)
Output:
0 English 1 Math --- 0 English 1 Math
If you slice from the middle, like subjects[2:4], pass start=2 so the counter still matches the real indexes.
enumerate() With A Dictionary
This shows up a lot in lab exams, and it makes students panic because it needs two levels of unpacking. marks.items() gives you (key, value) pairs, and enumerate() wraps each of those in another pair with a counter.
marks = {"Math": 85, "Science": 90, "English": 78}
for rank, (subject, score) in enumerate(marks.items(), start=1):
print(rank, subject, score)
Output:
1 Math 85 2 Science 90 3 English 78
The parentheses in (subject, score) are required. They tell Python to unpack the inner pair. Without them, you get an error. If you loop over the dictionary itself instead of .items(), you only get the keys.
enumerate() vs. range(len())
Students often mix these up. Here is how they compare:
| Criteria | enumerate() | range(len()) |
|---|---|---|
| Gives you | The index and the value together | Only the index. You look up the value yourself. |
| Readability | Clear | Wordier |
| Risk of mistakes | Lower | Higher (mixing up i and list[i]) |
| Works on any iterable | Yes, even things with no length | No, needs something with len() |
| Best for | You need both index and value | You only need the index, or you need custom steps like every other item |
Most teachers prefer enumerate() when you need both, because it shows your intent clearly. range() is still the right tool when you just need to count, or when you need to skip around with a step.
Tips For Writing Better Loops
- Loop over items directly. Write
for fruit in fruitsinstead offor i in range(len(fruits))unless you really need the index. If you need both, useenumerate(). - Use
forwhen you know what you are looping over. Savewhilefor cases where you do not know how many rounds you need, like reading input until the user types "quit." - Use built-in functions when you can.
sum(),max(),min(),sorted(), andany()replace many hand-written loops and are faster. - Avoid nested loops you do not need. A loop inside a loop over big data gets slow fast. Often a set or dictionary lookup can replace the inner loop.
- Keep the loop body short. If it grows long, move the logic into a function.
- Keep indentation consistent. Use 4 spaces. Mixing tabs and spaces causes errors.
Common Mistakes With Loops And enumerate()
These are the mistakes we see most often in student assignments.
Loop mistakes:
- Forgetting to update the counter in a
whileloop. The condition never becomes false, and you get an infinite loop. - Expecting
range(5)to include 5. It stops at 4. - Mixing up
breakandcontinue.breakends the whole loop.continueonly skips one round. - Changing a list while looping over it. This skips items without any error message, as you can see below.
numbers = [1, 2, 2, 3, 4]
for n in numbers: # Removing items while looping over the same list
if n == 2:
numbers.remove(n)
print(numbers) # One 2 is still there!
numbers = [1, 2, 2, 3, 4]
numbers = [n for n in numbers if n != 2] # Build a new list instead
print(numbers)
Output:
[1, 2, 3, 4] [1, 3, 4]
When the first 2 is removed, everything shifts left, and the loop skips the second 2. Build a new list instead, or loop over a copy with numbers[:].
enumerate() mistakes:
- Using one variable and expecting just the value.
for x in enumerate(items)gives you tuples, not values. - Thinking
startchanges the real indexes. It only changes the counter you see. - Combining
enumerate()withrange(len()).enumerate(range(len(items)))defeats the purpose. Useenumerate(items). - Forgetting the parentheses when unpacking dictionary items. Write
for i, (key, value) in enumerate(d.items()).
For more bugs like these and how to fix them, see our list of common Python errors in student assignments.
Conclusion
Loops show up in almost every Python program, from simple counting exercises to data processing and games. Once you understand how while and for work, how range() counts, and when to use break and continue, most looping problems get much easier.
enumerate() is the next step up. It removes manual index tracking, cuts down on off-by-one errors, and makes your code easier for your teacher to read. Start using it whenever you need both the position and the value.
If you want practice, our list of Python project ideas for beginners has plenty of projects that use loops. And if a graded assignment has you stuck, our Python assignment help team can walk you through it.
Takeaways:
- A
whileloop repeats while a condition is true. Always make sure something changes so it can end. - A
forloop goes through each item in a sequence. Pair it withrange()to repeat a set number of times. range(start, stop, step)never includes the stop value.breakexits a loop,continueskips one round, andpassis a placeholder.enumerate(iterable, start=0)gives you the index and the value together. It returns an enumerate object, which you can turn into a list withlist().- Do not change a list while you loop over it. Build a new list or loop over a copy.
Frequently Asked Questions
1. What are the types of loops in Python?
Python has two loop keywords: while and for. A while loop repeats as long as a condition is true. A for loop goes through each item in a sequence, like a list, a string, or range(). Python has no separate "for each" or "do-while" loop.
2. What does enumerate() do in Python?
enumerate() adds a counter to any iterable. When you loop over it, you get the index and the value together, so you do not need to track the index yourself. The counter starts at 0 by default, but you can change it with the start argument.
3. Does enumerate() make my program slower?
No, not in any way that matters. It runs in the same O(n) time as a regular loop and does not build a new list in memory. It is also a bit faster and cleaner than writing range(len()) and looking up each value by index.
4. What is the difference between break and continue?
break ends the loop completely, and the program moves to the code after it. continue skips only the rest of the current round, and the loop moves on to the next item.
5. Why do teachers recommend enumerate() in exams?
Because it shows your intent clearly. It tells the grader you need both the position and the value, without extra counter variables or index lookups. That makes your code easier to check and less likely to have off-by-one mistakes.
6. Can index mistakes cause real bugs?
Yes. Off-by-one errors and mixed-up indexes are among the most common logic bugs, in class and in real software. Using enumerate() keeps the index and the value in sync, which removes a whole group of these mistakes.




