Chapters
Python114 chapters

CollectionsChapter 29 of 114

Loop Lists

Walk a list properly, with the index when you need it and without when you do not.

Loop over the items

for hands you each item in turn. You almost never need the index:

Python
names = ["Ada", "Grace", "Katherine"]
for name in names:
    print(name)

Output

Ada
Grace
Katherine

You will see this written with range(len(...)) by people arriving from other languages. It works, and it is noisier:

Python
names = ["Ada", "Grace"]
for i in range(len(names)):
    print(names[i])

Output

Ada
Grace

enumerate when you want the position too

Python
names = ["Ada", "Grace", "Katherine"]
for i, name in enumerate(names):
    print(i, name)

Output

0 Ada
1 Grace
2 Katherine

Start the count somewhere else with start, which is how you get human numbering without adding one everywhere:

Python
names = ["Ada", "Grace"]
for number, name in enumerate(names, start=1):
    print(f"{number}. {name}")

Output

1. Ada
2. Grace

zip to walk two lists together

Python
names = ["Ada", "Grace"]
years = [1815, 1906]
for name, year in zip(names, years):
    print(name, year)

Output

Ada 1815
Grace 1906

zip stops at the shorter list. That silence is occasionally a bug, so pass strict=True when the lengths ought to match:

Python
try:
    for a, b in zip([1, 2, 3], [1, 2], strict=True):
        print(a, b)
except ValueError as problem:
    print("ValueError:", problem)

Output

1 1
2 2
ValueError: zip() argument 2 is shorter than argument 1

Looping backwards and in order

Python
names = ["Ada", "Grace", "Katherine"]
for name in reversed(names):
    print(name)

Output

Katherine
Grace
Ada
Python
for name in sorted(["Grace", "Ada", "Katherine"]):
    print(name)

Output

Ada
Grace
Katherine

Both hand back something new and leave the original list alone.

Nested loops

A loop inside a loop walks a grid:

Python
grid = [[1, 2], [3, 4]]
for row in grid:
    for value in row:
        print(value)

Output

1
2
3
4

break and continue

break leaves the loop; continue skips to the next item:

Python
for n in [1, 2, 3, 4, 5]:
    if n == 4:
        break
    if n % 2 == 0:
        continue
    print(n)

Output

1
3

Do not change the list you are looping over

Adding or removing while iterating shifts the positions under you. Build a new list, or loop over a copy:

Python
numbers = [1, 2, 3, 4]
for n in numbers[:]:
    if n % 2 == 0:
        numbers.remove(n)
print(numbers)

Output

[1, 3]

The [:] makes a copy to walk, so the removals from the real list do not disturb the loop.

Test yourself

2 questions

What does enumerate(names, start=1) give you?

Show the answer

Pairs of number and item, counting from 1 — It saves adding one to the index everywhere you want human numbering.

What does zip() do when the two lists are different lengths?

Show the answer

Stops at the shorter one — That silence can hide a bug. Pass strict=True when the lengths ought to match.

Next chapter

List Comprehension

Build a list from another one in a single readable line.