Python Loops and enumerate(): For, While, break & continue (With Examples)

what is loop in python?

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

TopicSummary
What a loop doesRuns a block of code over and over, until a condition is false or there are no items left.
while loopRepeats as long as a condition is true. Best when you do not know how many times it will run.
for loopGoes through each item in a sequence, like a list, a string, or range(). Best when you know what you are looping over.
Loop controlbreak 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.

Diagram of how a loop in Python checks a condition and repeats a block of code

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.

Flowchart of a while loop in Python

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:

  • count starts at 1, and limit is 5.
  • Before each round, Python checks count <= limit. While that is true, it prints a line.
  • count += 1 adds 1 each time. After the fifth round, count is 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().

Diagram of a for loop using range() in Python

range() can take one, two, or three arguments:

  • range(stop) counts from 0 up to, but not including, stop.
  • range(start, stop) counts from start up to, but not including, stop.
  • range(start, stop, step) counts by step. 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.

Diagram of a for loop going through each item of a list or string

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 index i and the value my_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

How enumerate() in Python pairs each item with its index

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:

Criteriaenumerate()range(len())
Gives youThe index and the value togetherOnly the index. You look up the value yourself.
ReadabilityClearWordier
Risk of mistakesLowerHigher (mixing up i and list[i])
Works on any iterableYes, even things with no lengthNo, needs something with len()
Best forYou need both index and valueYou 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 fruits instead of for i in range(len(fruits)) unless you really need the index. If you need both, use enumerate().
  • Use for when you know what you are looping over. Save while for 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(), and any() 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 while loop. The condition never becomes false, and you get an infinite loop.
  • Expecting range(5) to include 5. It stops at 4.
  • Mixing up break and continue. break ends the whole loop. continue only 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 start changes the real indexes. It only changes the counter you see.
  • Combining enumerate() with range(len()). enumerate(range(len(items))) defeats the purpose. Use enumerate(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 while loop repeats while a condition is true. Always make sure something changes so it can end.
  • A for loop goes through each item in a sequence. Pair it with range() to repeat a set number of times.
  • range(start, stop, step) never includes the stop value.
  • break exits a loop, continue skips one round, and pass is 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 with list().
  • 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.