PythonBeginner 13 min Lesson 8 of 30

Day 8 — Loops

Repeat work without repeating yourself. Learn for loops over collections, while loops for unknown counts, and the helpers that keep loops readable.

Python · Lesson 8 of 30
0/30 done(0%)

What is it? #

A loop repeats a block of code. Python has two: for, which walks through a collection, and while, which keeps going until a condition stops being true.

The Python for loop is different from the C-style counter loop many people expect. You do not manage an index; you say "for each item in this thing" and Python hands you the items one at a time.

When you genuinely need positions, enumerate() gives you the index and the item together. When you need to walk two collections side by side, zip() pairs them up.

break leaves the loop immediately. continue skips the rest of the current pass and moves to the next item. Both are fine in moderation and confusing when overused.

Think of it like this #

A for loop is going down a checklist — you deal with each line once and then you are finished, because the list has an end.

A while loop is boiling water: you keep checking "is it boiling yet?" and stop when it is. If you never check properly, you stand at the stove forever, which is exactly what an infinite loop is.

Simple example #

You have a list of orders. You want to print each one with its position, skip cancelled ones, stop entirely if you hit a corrupt record, and separately retry a network call up to three times.

Code #

PYTHON
orders = ["A-101", "A-102", "CANCELLED", "A-104", "CORRUPT", "A-106"]

for index, order in enumerate(orders, start=1):
    if order == "CANCELLED":
        continue                 # skip this one, keep going
    if order == "CORRUPT":
        print("Stopping — bad record found")
        break                    # leave the loop entirely
    print(index, order)

# Walking two lists together
names = ["Ravi", "Anita", "Sam"]
scores = [88, 92, 75]
for name, score in zip(names, scores):
    print(f"{name}: {score}")

# Counting with range
for i in range(3):
    print("attempt", i)          # 0, 1, 2

# while — repeat until something changes
attempts = 0
connected = False
while not connected and attempts < 3:
    attempts += 1
    connected = attempts == 3    # pretend the third try works
print("connected after", attempts, "attempts")

# for/else — the else runs only if no break happened
for order in orders:
    if order.startswith("A-999"):
        print("found it")
        break
else:
    print("no matching order")

How it works #

enumerate(orders, start=1) yields pairs like (1, "A-101"), so the loop can unpack into index and order. Without start=1 it begins at 0.

continue jumps back to the top of the loop for the next item, so the print at the bottom never runs for cancelled orders. break abandons the loop completely — the remaining items are never seen.

zip(names, scores) pairs items by position and stops at the shorter list. That silent truncation is worth knowing about: if your lists are different lengths, you lose the tail without a warning.

range(3) produces 0, 1, 2 — the end value is excluded, matching how slices work. range does not build a list in memory; it generates numbers as needed.

The while loop has two exit conditions joined with and, which is the standard shape for retry logic: stop when it worked, or when you have tried enough times. Note attempts += 1 happens first, so the counter always moves and the loop cannot spin forever.

The for/else at the end is unusual and genuinely useful: the else runs only when the loop finished without hitting break. It is the clean way to express "searched everything and found nothing".

Real-world use #

Loops are how you process anything that arrives in bulk: rows from a query, files in a directory, records in a CSV, messages from a queue, pages from a paginated API.

Retry loops with a cap are everywhere in production code, because networks fail intermittently. The cap matters — an uncapped retry loop against a failing service turns one outage into two.

Reading a large file line by line is a loop over the file object itself, which streams instead of loading everything into memory. That difference decides whether your script handles a 4 GB log file or dies trying.

For simple transformations, the loop often gets replaced by a comprehension, which you will meet on Day 13. Loops stay the right tool when there is real logic inside, not just a mapping.

Common mistakes #

  • Writing a while loop whose condition never becomes false. Always make sure something inside the loop changes it.
  • Modifying a list while iterating over it. Build a new list or iterate over a copy.
  • Using range(len(items)) and then items[i] when you only need the items. Loop over the items directly, or use enumerate.
  • Forgetting that zip stops at the shortest input, silently dropping data.
  • Doing a database query inside a loop. One query per row is the classic cause of a slow endpoint — fetch once, then loop.

Practice #

Given temps = [31, 28, 35, 40, 22, 38], print each temperature with its position starting at 1, skip anything below 25, and stop the loop if a value above 39 appears. Then write a while loop that halves a number until it drops below 1, printing each step.

Quick quiz

  1. 1. What does `enumerate(items, start=1)` produce?

  2. 2. What is the difference between `break` and `continue`?

  3. 3. What does `range(3)` produce?

  4. 4. What happens when you `zip` a 3-item list with a 5-item list?

  5. 5. When does the `else` block of a `for` loop run?

Summary

  • `for` walks through a collection; `while` repeats until a condition changes.
  • Use enumerate for positions and zip for parallel collections instead of manual indexes.
  • `break` exits, `continue` skips — use both sparingly so the flow stays readable.
  • Every while loop needs something that makes its condition eventually false.
  • Never run a database query inside a loop when one query outside would do.