← back to section

Looking at five records out of five hundred and hoping the rest are the same is a compromise. A loop removes it: going through all five hundred costs the same as going through one.

A loop over a list

live example

statuses = ["NEW", "PAID", "SHIPPED"]

for status in statuses:
    print(status)
Run

Running examples is part of paid access. There the same code runs inside the article: editor, run and check next to the paragraph. Three free days →

It reads literally: "for each status in statuses — print the status". You do not declare the variable beforehand: the loop puts the next element into it on every pass.

The loop body is indented, like an if. Everything indented repeats; everything not indented runs once, after the loop.

Practice here: Walk a list with a loop

Accumulating a sum

A sum is collected in a separate variable — an accumulator. The whole question is where to declare it.

live example

# the wrong way
items = [{"qty": 1, "price": 4990}, {"qty": 2, "price": 890}]

for item in items:
    total = 0
    total += item["qty"] * item["price"]

print(total)     # 1780 — only the last item survived
Run

Running examples is part of paid access. There the same code runs inside the article: editor, run and check next to the paragraph. Three free days →

live example

# the right way
items = [{"qty": 1, "price": 4990}, {"qty": 2, "price": 890}]

total = 0
for item in items:
    total += item["qty"] * item["price"]

print(total)     # 6770
Run

Running examples is part of paid access. There the same code runs inside the article: editor, run and check next to the paragraph. Three free days →

An accumulator inside the loop is reset on every pass. There is no error — just a wrong number, visible only in the result. total = total + x is usually shortened to total += x.

Practice here: Sum up the order items · Total of paid orders

A counter

A counter works the same way, adding one instead:

live example

orders = [
    {"id": "ord-042", "status": "PAID"},
    {"id": "ord-043", "status": "CANCELLED"},
]

cancelled = 0
for order in orders:
    if order["status"] == "CANCELLED":
        cancelled += 1

print(cancelled)     # 1
Run

Running examples is part of paid access. There the same code runs inside the article: editor, run and check next to the paragraph. Three free days →

Note the double indent: the if sits inside the for, and its body is further right still. Indents show nesting.

Practice here: Count orders by status

A loop over a dict

A dict is walked the same way — by keys, or by pairs at once:

live example

order = {"id": "ord-042", "status": "PAID", "total": 4990}

for key in order:
    print(key)

for key, value in order.items():
    print(f"{key} = {value}")
Run

Running examples is part of paid access. There the same code runs inside the article: editor, run and check next to the paragraph. Three free days →

items() hands out a ready pair, unpacked into two variables at once. Handy for checking every field in one go — that none of them is empty, for example.

Practice here: Iterate keys and values

Stopping early

Once the element you wanted has turned up, there is no point reading the list to the end.

live example

orders = [
    {"id": "ord-042", "status": "PAID"},
    {"id": "ord-043", "status": "CANCELLED"},
]

found = None
for order in orders:
    if order["id"] == "ord-043":
        found = order
        break          # no point searching further

print(found)
Run

Running examples is part of paid access. There the same code runs inside the article: editor, run and check next to the paragraph. Three free days →

break leaves the loop entirely, continue skips only the current pass and moves on to the next:

live example

orders = [
    {"id": "ord-042", "status": "DRAFT"},
    {"id": "ord-043", "status": "PAID"},
]

for order in orders:
    if order["status"] == "DRAFT":
        continue       # drafts do not count
    print(order["id"])
Run

Running examples is part of paid access. There the same code runs inside the article: editor, run and check next to the paragraph. Three free days →

When you need the element number

Sometimes the element's position is needed alongside the element itself — to number the printed lines, say.

live example

orders = ["ord-042", "ord-043", "ord-044"]

# the wrong way: walking by index and digging the element out of the list
for i in range(len(orders)):
    print(i + 1, orders[i])

# the right way: enumerate hands out the number along with the element
for number, order in enumerate(orders, start=1):
    print(number, order)
Run

Running examples is part of paid access. There the same code runs inside the article: editor, run and check next to the paragraph. Three free days →

Both forms print the same thing, but the second leaves nothing to get wrong: the number arrives together with the element.

Building a new list

A common task: pull one field out of a list of dicts.

live example

orders = [
    {"id": "ord-042", "status": "PAID"},
    {"id": "ord-043", "status": "CANCELLED"},
]

ids = []
for order in orders:
    ids.append(order["id"])

print(ids)
Run

Running examples is part of paid access. There the same code runs inside the article: editor, run and check next to the paragraph. Three free days →

The short form of the same thing is called a list comprehension — it shows up often in other people's code:

live example

orders = [
    {"id": "ord-042", "status": "PAID"},
    {"id": "ord-043", "status": "CANCELLED"},
]

ids = [order["id"] for order in orders]
cancelled = [order for order in orders if order["status"] == "CANCELLED"]
print(ids)
print(cancelled)
Run

Running examples is part of paid access. There the same code runs inside the article: editor, run and check next to the paragraph. Three free days →

Write whichever is clearer: the long form is more readable, the short one more compact.

Common mistakes

Modifying a list while iterating it. Removing elements from the list you are walking skips items. Build a new list and replace the old one.

Wrong indent. A line that should be inside the loop ends up outside and runs once instead of a hundred times. Printing intermediate values catches it.

In short

  • for item in items walks every element; no need to declare the variable.
  • The accumulator (total = 0, counter = 0) is declared before the loop, or it resets on every pass.
  • Walk a dict through .items() — key and value at once.
  • break leaves the loop, continue skips a pass.
  • enumerate hands out the number with the element, and a comprehension [order["id"] for order in orders] is a loop with collection in short form.