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:
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:
names = ["Ada", "Grace"]
for i in range(len(names)):
print(names[i])Output
Ada Grace
enumerate when you want the position too
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:
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
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:
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
names = ["Ada", "Grace", "Katherine"]
for name in reversed(names):
print(name)Output
Katherine Grace Ada
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:
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:
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:
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 questionsWhat 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.
List Comprehension
Build a list from another one in a single readable line.