enumerate and building lists in a loop
Three loop patterns you'll use every day.
enumerate gives you the index *and* the value together, so you don't manage a separate counter. for i, value in enumerate(items): yields (0, first), (1, second), … Pass start=1 to count from 1 instead of 0 — handy for human-facing line numbers.
Build-a-list-in-a-loop: start with an empty result = [] *before* the loop, then result.append(...) each pass. After the loop, result holds everything you collected. (Initialise the accumulator outside the loop, or it resets every pass.)
Filter as you build: combine the two — only append items that pass a test. An if inside the loop decides what makes the cut, so the result contains just the matches. This is the manual version of what a list comprehension does in one line (coming up later) — and the version to reach for when the logic is more than a single expression.
Syntax
for i, value in enumerate(items): # i = 0, 1, 2, ...
...
for i, value in enumerate(items, start=1): # i = 1, 2, 3, ...
...
# Build (and filter) a list:
result = [] # before the loop
for item in items:
if keep(item): # optional filter
result.append(item)
return resultWorked examples
enumerate with start=1 for 1-based numbering
def number_lines(lines):
result = []
for i, line in enumerate(lines, start=1):
result.append(f"{i}: {line}")
return result
print(number_lines(["alpha", "beta"]))
# ['1: alpha', '2: beta']Filter while building — keep only the matches
def collect_errors(events):
result = []
for event in events:
if "ERROR" in event:
result.append(event)
return result
print(collect_errors(["OK", "ERROR bad", "OK", "ERROR timeout"]))
# ['ERROR bad', 'ERROR timeout']Accumulate with a filter (sum only the positives)
def sum_positives(numbers):
total = 0
for n in numbers:
if n > 0:
total += n
return total
print(sum_positives([3, -1, 0, 7, -2])) # 10Common mistakes & gotchas
Initialising the accumulator inside the loop
result = [] (or total = 0) must sit *before* the loop. Put it inside and it resets every pass, leaving you with only the last item. The accumulator is set up once, then updated each iteration.
Using range(len(items)) instead of enumerate
for i in range(len(items)): item = items[i] works but is clumsy and easy to get wrong. for i, item in enumerate(items): gives you both cleanly — it's the Pythonic way.
Forgetting start= when you want 1-based numbers
enumerate(items) counts from 0. If you're labelling lines or ranks for humans, you usually want enumerate(items, start=1), or you'll be off by one.
Why it matters
Reading a collection, transforming or filtering it, and collecting the results is the bread and butter of backend work — processing log lines, request payloads, query rows. `enumerate` and the build-a-list pattern are the readable, idiomatic way to do it, and they're the mental model that list comprehensions compress.