Public code review lab
Why does this Python total work for a list but fail for a generator?
Published
Published by Unrust. Scoring and editorial method
Quick answer
The generator expression passed to any reads the underlying iterable. Because both quantities are non-negative, it reaches the end while looking for a true condition. A list can be traversed again, but a generator cannot be restarted by wrapping it in another expression. The repair validates and accumulates in one pass. It also avoids materializing an arbitrarily large input.
Read the contract before the patch
Accept a finite iterable of rows containing integer quantity values. Reject a negative quantity with ValueError and otherwise return the sum. A list and a one-shot generator containing the same rows must give the same result.
Predict the result before reading the repair. Use a small counterexample to separate the code’s behavior from the behavior you expected.
def total_quantity(lines):
if any(row["quantity"] < 0 for row in lines):
raise ValueError("negative quantity")
return sum(row["quantity"] for row in lines)Compare the repair against the same inputs
The generator expression passed to any reads the underlying iterable. Because both quantities are non-negative, it reaches the end while looking for a true condition. A list can be traversed again, but a generator cannot be restarted by wrapping it in another expression. The repair validates and accumulates in one pass. It also avoids materializing an arbitrarily large input.
def total_quantity(lines):
total = 0
for row in lines:
quantity = row["quantity"]
if quantity < 0:
raise ValueError("negative quantity")
total += quantity
return total| Input | Original | Repair |
|---|---|---|
| List containing 2 and 5 | 7 | 7 |
| Generator yielding 2 and 5 | 0 | 7 |
| Empty generator | 0 | 0 |
| Generator yielding 2 and -1 | ValueError | ValueError |
Extend the review
The contract assumes finite input and integer quantities. This example does not validate row schemas, handle an infinite iterable or roll back external side effects.
Change one assumption, predict a new outcome, then run the example in your own environment. The public lab repository contains the snippets and their checks. These examples teach review reasoning; they do not measure coding ability.
Interactive reasoning check
Make your prediction
Read the reasoning without answering
The generator expression passed to any reads the underlying iterable. Because both quantities are non-negative, it reaches the end while looking for a true condition. A list can be traversed again, but a generator cannot be restarted by wrapping it in another expression. The repair validates and accumulates in one pass. It also avoids materializing an arbitrarily large input.
A small practice loop
- 01State the input contract in your own words.
- 02Predict each boundary result before running the code.
- 03Compare the original and repair with exactly the same input.
- 04Write one additional case and explain what it establishes.
Common questions
Is this a scored Unrust assessment?
No. This is a fully public, worked teaching example. Its answers are intentionally available and it produces no diagnostic score.
Can I reuse the example in a tutorial?
Yes. The public lab source is MIT licensed. Keep the license, state the input contract and link to the example and its verification date.
Limits of this guide
The contract assumes finite input and integer quantities. This example does not validate row schemas, handle an infinite iterable or roll back external side effects.
Sources and scope
Original public teaching material authored for Unrust and execution-checked on 21 October 2026. It is separate from the diagnostic and Daily puzzle banks.
- Iterators in the functional programming HOWTO
Python documentation
Iterators advance through a stream; exhausting one does not reset it.
Check your own starting point
Unrust uses short, timed, unassisted drills to give developers a per-skill snapshot. One session cannot explain the cause of a result, but it can show you what is worth practicing next.
Take the free diagnostic