Skip to content
  • Loops & Iteration Patterns · Python

Loops & Iteration Patterns

LearnViaNotes @learnvianotes· 6 min read

Python's for walks over any iterable — there is no C-style for (i = 0; …). This topic collects the loop patterns, helpers and pitfalls you meet every day.

range in detail

Python
print(list(range(5)))                 # [0, 1, 2, 3, 4]
print(list(range(2, 12, 3)))          # [2, 5, 8, 11]
print(list(range(5, 0, -1)))          # [5, 4, 3, 2, 1]
print(list(range(3, 0)))              # []   ← empty: a negative step is needed to count down
r = range(0, 10**12, 2)               # no list is built — O(1) memory
print(len(r), r[10], r[-1])           # 500000000000 20 999999999998
print(999_999 in r, 1_000 in r)       # False True   ← O(1) arithmetic check
GoalLoop header
0 … n−1for i in range(n)
1 … n inclusivefor i in range(1, n + 1)
n−1 down to 0for i in range(n - 1, -1, -1) or reversed(range(n))
Every other indexfor i in range(0, n, 2)
Items and their indexfor i, x in enumerate(xs)
Two lists in stepfor a, b in zip(xs, ys)
Neighbouring pairsfor a, b in zip(xs, xs[1:]) or itertools.pairwise(xs)

while loops and while … else

Use while when you don't know the number of iterations in advance. Like for, it takes an else that runs only if the loop ended without break.

Python
n, steps = 27, 0
while n != 1:                         # Collatz sequence
    n = n // 2 if n % 2 == 0 else 3 * n + 1
    steps += 1
print(steps)                          # 111

def is_prime(n):
    if n < 2:
        return False
    d = 2
    while d * d <= n:
        if n % d == 0:
            break                     # found a divisor
        d += 1
    else:
        return True                   # no break → no divisor found
    return False

print([k for k in range(20) if is_prime(k)])   # [2, 3, 5, 7, 11, 13, 17, 19]
Python
attempts = 0
while True:                           # the do-while idiom: body runs at least once
    attempts += 1
    if attempts * attempts > 20:
        break
print(attempts)                       # 5

Breaking out of nested loops

break only leaves the innermost loop. Three ways out of two:

Python
grid = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# 1. A flag checked by the outer loop
found = None
for r, row in enumerate(grid):
    for c, val in enumerate(row):
        if val == 5:
            found = (r, c)
            break
    if found:
        break
print(found)                          # (1, 1)

# 2. Put the loops in a function and return (usually the cleanest)
def find(grid, target):
    for r, row in enumerate(grid):
        for c, val in enumerate(row):
            if val == target:
                return r, c
    return None
print(find(grid, 8), find(grid, 0))   # (2, 1) None

# 3. One flat loop over all coordinates
from itertools import product
hit = next(((r, c) for r, c in product(range(3), range(3)) if grid[r][c] == 9), None)
print(hit)                            # (2, 2)

Iterating dicts, in order, in reverse, in parallel

Python
prices = {"tea": 20, "coffee": 35, "juice": 50}
print([k for k in prices])                        # ['tea', 'coffee', 'juice']
print([f"{k}={v}" for k, v in prices.items()])    # ['tea=20', 'coffee=35', 'juice=50']
print(sorted(prices, key=prices.get, reverse=True))   # ['juice', 'coffee', 'tea']

names = ["asha", "ravi", "kiran"]
scores = [91, 84, 77]
print(list(enumerate(names, start=1)))    # [(1, 'asha'), (2, 'ravi'), (3, 'kiran')]
print(dict(zip(names, scores)))           # {'asha': 91, 'ravi': 84, 'kiran': 77}
print(list(zip(names, [1, 2])))           # [('asha', 1), ('ravi', 2)]   ← stops at the shortest
try:
    list(zip(names, [1, 2], strict=True)) # 3.10+: insist on equal lengths
except ValueError as e:
    print(e)                              # zip() argument 2 is shorter than argument 1
print(list(reversed(names)))              # ['kiran', 'ravi', 'asha']

pairs = [("a", 1), ("b", 2)]
letters, numbers = zip(*pairs)            # "unzip"
print(letters, numbers)                   # ('a', 'b') (1, 2)

Don't modify a collection while looping over it

Python
nums = [1, 2, 2, 3, 4]
for x in nums:
    if x % 2 == 0:
        nums.remove(x)        # shifts later items left → the loop skips one
print(nums)                   # [1, 2, 3]   ← a 2 survived!

nums = [1, 2, 2, 3, 4]
print([x for x in nums if x % 2])       # [1, 3]   ← build a new list instead

d = {"a": 1, "b": 2}
try:
    for k in d:
        if d[k] == 1:
            del d[k]
except RuntimeError as e:
    print(e)                  # dictionary changed size during iteration
d = {k: v for k, v in d.items() if v != 1}
print(d)                      # {'b': 2}

Sentinel loops & iter(callable, sentinel)

Python
import io
from functools import partial

stream = io.StringIO("alpha\nbeta\n\ngamma\n")
lines = []
while (line := stream.readline().rstrip("\n")):   # stop at the first empty line
    lines.append(line)
print(lines)                                      # ['alpha', 'beta']

f = io.StringIO("abcdefgh")
chunks = list(iter(partial(f.read, 3), ""))       # call f.read(3) until it returns ""
print(chunks)                                     # ['abc', 'def', 'gh']

Loop variables & scope

Python
for i in range(3):
    pass
print(i)                      # 2   ← the loop variable survives the loop

squares = [j * j for j in range(3)]
print("j" in dir())           # False   ← comprehension variables don't leak

Faster loops

SlowerFasterWhy
total = 0 + for x in xs: total += xsum(xs)Built-ins loop in C
Loop + appendList comprehensionNo repeated .append lookup and call
if x in big_list inside a loopConvert to a set onceO(1) instead of O(n) per check
for i in range(len(xs)): xs[i]for x in xsNo indexing per step
s += piece in a loop''.join(pieces)Avoids O(n²) copying
obj.method looked up each timem = obj.method before the loopOne attribute lookup instead of n

When would you use for … else?

How do you iterate over two lists at the same time?

Why is removing items from a list while iterating over it a bug?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report