Python Fundamentals
Loops & Iteration Basics
Python's for loop iterates directly over items in a collection — there's no manual index management like in C-style languages.
Jr Codex Python Notes
Level: Beginner Prerequisites: Chapter 10 Time to complete: ~25 minutes
Table of Contents
- The
forLoop - The
range()Function - The
whileLoop breakandcontinue- The
elseClause on Loops - Looping with
enumerate()andzip() - Common Pitfalls
- Summary & Next Steps
1. The for Loop
Python's for loop iterates directly over items in a collection — there's no manual index management like in C-style languages.
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# Also works directly on strings, dicts, sets, tuples — anything "iterable"
for char in "abc":
print(char) # a b cfor item in collection:
─────────────────────────────────────
Python pulls items ONE AT A TIME from the collection
and binds each to `item` for the duration of that pass.
─────────────────────────────────────
2. The range() Function
When you need a sequence of numbers (not an existing collection), use range():
for i in range(5): # 0, 1, 2, 3, 4 — stop is EXCLUSIVE
print(i)
for i in range(2, 6): # 2, 3, 4, 5 — start, stop
print(i)
for i in range(0, 10, 2): # 0, 2, 4, 6, 8 — start, stop, step
print(i)
for i in range(10, 0, -1): # 10, 9, 8, ..., 1 — counting down
print(i)| Call | Produces |
|---|---|
range(5) | 0, 1, 2, 3, 4 |
range(2, 6) | 2, 3, 4, 5 |
range(0, 10, 2) | 0, 2, 4, 6, 8 |
range(5, 0, -1) | 5, 4, 3, 2, 1 |
range() is lazy — it doesn't build a full list in memory, just generates numbers as needed (the same underlying idea behind generators, covered in Module 5).
3. The while Loop
Repeats as long as a condition remains true. Use this when you don't know the number of iterations in advance.
count = 0
while count < 5:
print(count)
count += 1 # without this, the loop runs forever!
# Common pattern: loop until a condition is met
import random
target = random.randint(1, 10)
guess = None
attempts = 0
while guess != target:
guess = random.randint(1, 10) # simulate a guess
attempts += 1
print(f"Found {target} after {attempts} attempts")The #1 while-loop bug: forgetting to update the condition variable, causing an infinite loop. Always double-check that something inside the loop moves you toward the exit condition.
4. break and continue
# break — exit the loop immediately
for num in range(1, 20):
if num == 5:
break
print(num) # prints 1, 2, 3, 4 — then stops
# continue — skip to the next iteration
for num in range(1, 10):
if num % 2 == 0:
continue # skip even numbers
print(num) # prints 1, 3, 5, 7, 9break vs continue
─────────────────────────────────────
break → exits the loop entirely, no more iterations
continue → skips the REST of the current iteration only
─────────────────────────────────────
5. The else Clause on Loops
An often-overlooked Python feature: loops can have an else block that runs only if the loop completes without hitting break.
def find_prime_factor(n):
for i in range(2, n):
if n % i == 0:
print(f"{n} is divisible by {i}")
break
else:
print(f"{n} is prime") # only runs if the loop never broke
find_prime_factor(15) # "15 is divisible by 3"
find_prime_factor(13) # "13 is prime"This is genuinely useful for "search and confirm not found" logic — no flag variable needed.
6. Looping with enumerate() and zip()
Two of the most useful loop helpers in everyday Python.
enumerate() — get index and value together
fruits = ["apple", "banana", "cherry"]
# Instead of manual index tracking:
for i in range(len(fruits)):
print(i, fruits[i])
# Idiomatic:
for i, fruit in enumerate(fruits):
print(i, fruit)
for i, fruit in enumerate(fruits, start=1): # start counting from 1
print(f"{i}. {fruit}")zip() — loop over multiple sequences together
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
for name, age in zip(names, ages):
print(f"{name} is {age} years old")
# zip stops at the SHORTEST iterable
a = [1, 2, 3]
b = ["x", "y"]
print(list(zip(a, b))) # [(1, 'x'), (2, 'y')] — no error, just stops early7. Common Pitfalls
# Pitfall 1: modifying a list while iterating over it
numbers = [1, 2, 3, 4, 5]
for n in numbers:
if n % 2 == 0:
numbers.remove(n) # ✗ skips elements — indices shift as you remove!
# Result is unpredictable: [1, 3, 5] is NOT guaranteed here
# Fix: iterate over a copy, or build a new list
numbers = [1, 2, 3, 4, 5]
numbers = [n for n in numbers if n % 2 != 0] # list comprehension (Module 2)
print(numbers) # [1, 3, 5]
# Pitfall 2: off-by-one with range()
for i in range(1, 10): # Does this include 10? NO — range stop is exclusive
pass
for i in range(1, 11): # ✓ this includes 10
pass
# Pitfall 3: infinite while loop
count = 0
# while count < 5:
# print(count) # forgot count += 1 — runs forever!8. Summary & Next Steps
Key Takeaways
forloops iterate directly over collection items — no manual indexing needed.range(start, stop, step)generates numbers lazily;stopis always exclusive.whileloops run until a condition becomes false — always ensure the loop body moves toward that condition.breakexits a loop entirely;continueskips to the next iteration; a loop'selseruns only ifbreakwas never hit.enumerate()andzip()are the idiomatic ways to get indices and to loop over multiple sequences in parallel.
Concept Check
- What does
range(2, 10, 3)produce? - Why is modifying a list while iterating over it dangerous?
- When does a
for/elseblock'selseclause execute?
Module 1 Complete — Next Module
You've now covered every core data type and control structure in Python. Module 2 builds on this foundation with functions — how to package logic into reusable, named blocks.
→ Module 2: Functions & Functional Basics
Jr Codex — 1-on-1 Personalized Coaching | Back to Module Index