Python Tutorial / Loop with for, range, enumerate and zip

A for loop processes items from an iterable. Iterate values directly when possible, use enumerate when you need a position, and use zip to read related collections together.

Iterate values or a numeric range

Python for loops are not limited to manually incrementing a list index. Lists and strings can be iterated directly. range(start, stop, step) excludes stop; a negative step counts down. A range is not a prebuilt list containing every number.

for value in range(1, 4):
    print(value)

This prints 1, 2 and 3 on separate lines. Treating stop as inclusive leads to an incorrect iteration count.

For the relevant APIs and platform requirements, see Python: functions.

Unpacking and consumption during iteration build on the rules demonstrated in Understand Tuples and Sequence Unpacking.

Pair names and amounts with display numbers

Save the complete code below as for_loop.py in a separate practice folder, using UTF-8. Run python for_loop.py in a terminal with your project virtual environment selected. Outside a virtual environment on macOS or Ubuntu, use python3 when that is your interpreter command.

names = ["coffee", "lunch", "bus"]
amounts = [3500, 8000, 2500]
for number, (name, amount) in enumerate(zip(names, amounts, strict=True), start=1):
    print(number, name, amount)
print(list(range(5, 0, -2)))

Expected output:

1 coffee 3500
2 lunch 8000
3 bus 2500
[5, 3, 1]

Check positions and equal-length requirements

enumerate provides a counter and an item. start=1 changes the display counter rather than the underlying list indexes. The nested unpacking receives that number and the name–amount pair produced by zip.

Ordinary zip stops when the shortest input ends. If equal lengths are required, strict=True makes a mismatch visible instead of silently omitting records. This option is available from Python 3.10. As records grow, a list of dictionaries may communicate their relationships better than separate parallel lists.

The first display number from enumerate(items, start=1) is 1, while the original list’s first index remains 0. Prefer unpacking the number and value instead of indexing the source with a display number. Plain zip stops at the shorter input; validate lengths or use strict=True when unequal lengths are an error.

Test boundaries and avoid mutation surprises

Deleting from the list currently being iterated can skip items as indexes shift. Collect changes separately or create a filtered result. Distinguish a read-only traversal from an operation that changes the source collection.

  1. Remove the final amount and observe the strict zip error.
  2. Remove strict=True and compare the two-row result, then restore both inputs and the option.
  3. Predict range(5, -1, -2): the sequence is still 5, 3, 1 because the stop value -1 is excluded.

An iterable with no items simply runs the loop zero times. Ensure any value used afterwards is initialized outside the loop when empty input is possible.