Python Loops — The Basics
Build a real mental model of Python loops: how the for loop walks any iterable without manual index work, when range() and while fit, how enumerate() hands you the index, and how break, continue and the loop else clause change the flow.
Introduction
A loop is how a program repeats work: instead of writing the same statement over and over, you write it once and let Python run it many times. Python has two loop keywords — for and while — and the whole subject comes down to knowing which one fits and what tools ride alongside them. Master that and repetition stops being a chore and becomes a single readable line.
Why two kinds? Because there are two different questions. Sometimes you already have a collection of things and want to visit each one — the lines of a file, the items in a list, the characters in a word. Other times you don't know how many rounds you'll need; you just want to keep going *until some condition changes*. The for loop answers the first question, the while loop the second, and almost every loop you ever write is one of those two shapes.
The mental model to hold onto is this: a for loop walks an iterable, and a while loop watches a condition. By the end of this guide you'll be able to reason about how a for loop hands you items with no manual counter, when range() earns its place, how enumerate() gives you the index cleanly, and how break, continue and the surprising loop else clause bend the flow of a loop.
Lessons
1. The for loop walks any iterable
The core idea of Python's for loop is that it does not count — it iterates. You hand it any *iterable* (a list, a string, a range, a dictionary, a file) and it hands you back one item at a time until the items run out. There is no counter to initialise, no length to check, no off-by-one to get wrong. This is the single biggest difference from the C-style for (i = 0; i < n; i++) loop that many languages force on you, and it is why Python loops read almost like English.
fruits = ["apple", "pear", "plum"]
for fruit in fruits:
print(fruit) # apple, then pear, then plum
Read it as "for each fruit in fruits." The loop variable fruit is rebound to the next item on every pass, and the indented body runs once per item. Because the loop pulls values directly, you rarely need to think about an index at all — a habit worth forming early, because reaching for a numeric counter out of reflex is the most common way beginners make Python loops harder than they are.
2. range() for counting
Sometimes you genuinely want to repeat something a fixed number of times, or count through a span of integers. That is what range() is for: it produces a lazy sequence of whole numbers that a for loop can walk. range(5) yields 0, 1, 2, 3, 4 — it starts at 0 and *stops before* the number you give it. Give it two arguments for a start and stop, or three to add a step.
for n in range(5):
print(n) # 0 1 2 3 4 (each on its own line)
print(list(range(2, 10, 2))) # [2, 4, 6, 8]
The stop value is *exclusive* — a deliberate choice that makes range(len(items)) line up exactly with the valid indices of a sequence, and makes adjacent ranges tile without overlap. range() is also memory-efficient: it never builds the whole list, it just remembers the start, stop and step and computes each value on demand, which is why range(1_000_000) costs almost nothing until you loop over it. See the full range() reference for every detail, including negative steps for counting downward.
3. The while loop watches a condition
A while loop is the tool for when you *don't* know the number of rounds ahead of time. It re-checks a condition before every pass and keeps looping as long as that condition stays true: retrying a request until it succeeds, reading input until the user quits, shrinking a number until it hits zero. Where a for loop is bounded by its iterable, a while loop is bounded only by when its condition flips to false — so *something in the body must move it toward that*, or the loop never ends.
countdown = 3
while countdown > 0:
print(countdown)
countdown -= 1 # <-- moves the condition toward False
print("lift off")
4. enumerate() when you need the index
Every so often you really do need the position — the index — of each item alongside its value: to number a list, to update a slot, to report *where* something was found. The clumsy way is to loop over range(len(seq)) and index back in; the Pythonic way is enumerate(), which wraps any iterable and yields (index, item) pairs. You unpack both in the loop header and never touch a manual counter.
fruits = ["apple", "pear", "plum"]
for i, fruit in enumerate(fruits):
print(i, fruit) # 0 apple, 1 pear, 2 plum
enumerate() reads better, avoids the off-by-one traps of manual indexing, and even lets you choose the starting number with enumerate(seq, start=1) for human-friendly "item 1, item 2" numbering. It is almost always the right answer when a loop needs both position and value — the enumerate() reference covers the details and contrasts it with the range(len(...)) anti-pattern it replaces.
5. break, continue and the loop else clause
Two keywords let you steer a loop from inside its body. break stops the loop immediately and jumps past it — perfect for a search that can quit the moment it finds a match. continue skips the rest of the current pass and moves straight to the next item, handy for filtering out cases you don't care about without deep nesting. Both work identically in for and while loops.
for n in range(10):
if n == 3:
continue # skip 3, keep going
if n == 6:
break # stop entirely at 6
print(n) # 0 1 2 4 5
Python adds a feature most languages lack: a loop can have an else clause. The else runs only if the loop finished normally — that is, if it was *not* ended by a break. It reads oddly at first, but it is the clean way to express "I searched the whole thing and never found it," with no flag variable to track. Pair it with break and the intent becomes obvious: break means found, else means exhausted.
for n in [4, 6, 8]:
if n % 2 == 1:
print("found an odd one")
break
else:
print("all even") # runs because no break happened
6. Comprehensions vs explicit loops
Not every loop should stay a loop. When a for loop exists only to build a *new* list — transforming each item, or keeping the ones that pass a test — Python offers a comprehension that says exactly that in one line: [expr for item in iterable if condition]. It replaces the create-empty-list-then-append pattern and reads as a single description of the result rather than a recipe for building it.
# explicit loop
squares = []
for n in range(1, 6):
squares.append(n * n)
# same thing as a comprehension
squares = [n * n for n in range(1, 6)] # [1, 4, 9, 16, 25]
The rule of thumb: use a comprehension when the loop's whole job is to *produce a collection*, and keep an explicit loop when the body *does something* — prints, saves, calls an API, or carries logic too involved to read on one line. A comprehension you have to squint at has stopped earning its concision; reach back for the plain loop.
7. Consolidation
That is the whole model. A for loop walks an iterable and hands you items with no counter; range() gives you integers to count with when you need them; a while loop repeats while a condition holds; enumerate() supplies the index when position matters; break, continue and the loop else clause steer the flow; and a comprehension collapses a build-a-list loop into one line. You understand loops when you can look at a repetition task and immediately say which of these shapes it is — everything else is detail hung on that frame.
Practice
Check your model before moving on. What does for n in range(1, 4): print(n) print, and why does it stop at 3? (Answer: 1 2 3 — range starts at the first argument and stops *before* the second, so 4 is never reached.)
And a flow check: in a for loop with an else clause, when does the else run? (Answer: only when the loop finishes without hitting a break.) Now open the online Python compiler and try it — loop over ["a", "b", "c"] with enumerate, print the index beside each letter, then rewrite it to start counting at 1 and confirm the numbers shift.
Next steps
You have the mental model — now put it to work. Follow how to loop with an index in Python for that common task done correctly, or browse runnable Python loop examples for copy-paste snippets. For the tools themselves, read the range() reference and the enumerate() reference, or revisit Python lists — the basics, the collection you will loop over most. Run anything live in the online Python compiler.
Frequently asked questions
What is the difference between a for loop and a while loop in Python?
for loop iterates over an iterable — it runs once per item and stops when the items run out. A while loop repeats as long as a condition stays true, so you use it when you don't know the number of rounds in advance.How do I loop a fixed number of times in Python?
range(): for n in range(5): runs the body five times with n going 0 through 4. range(stop) starts at 0 and stops before stop.How do I get the index while looping in Python?
enumerate(): for i, item in enumerate(seq): gives you the index and the value together. Pass start=1 to begin counting at one instead of zero.What does the else clause on a loop do?
else runs only if the loop finished without hitting a break. It is the clean way to express "the loop completed without finding what it searched for," with no flag variable needed.What is the difference between break and continue?
break stops the loop entirely and jumps past it. continue skips the rest of the current pass and moves on to the next item. Both work in for and while loops.