Skip to main content

Loops and Iteration

A for loop consumes an iterable. It is the default when values come from a collection, generator, file, or other iteration protocol.

for index, value in enumerate(values):
process(index, value)

for left, right in zip(left_values, right_values, strict=True):
compare(left, right)

Use range(start, stop, step) when the numbers themselves define the iteration, not merely to imitate indexing.

While loops

A while loop repeats while a condition remains truthy. Make initialization, progress, and termination visible:

attempts = 0
while attempts < maximum_attempts:
if try_operation():
break
attempts += 1
else:
raise RuntimeError("operation never succeeded")

The loop else runs only when the loop finishes without break. It is often useful for search exhaustion, but a helper function with an early return may be clearer.

Control statements

  • break exits the nearest loop.
  • continue starts its next iteration.
  • pass performs no operation; it is a syntactic placeholder.

Avoid deeply nested break logic; extract a function or maintain explicit state when several loops must terminate together.

Mutation during iteration

Changing the size or structure of the container being traversed can skip values, repeat work, or raise an error. Iterate over a copy, build a new collection, or separate discovery from mutation:

active = [item for item in items if item.enabled]

Iterators are consumable

Many iterators yield each value once. Converting to a list enables repeated passes but materializes all values. Preserve streaming when input may be large.

Source