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
breakexits the nearest loop.continuestarts its next iteration.passperforms 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.