unrust

Python iterator & mutable default explorer

Trace two classic Python state bugs side by side: one-shot generator exhaustion across two passes and shared mutable default list arguments across function calls.

Free to use · No sign-up · Inputs stay in your browser

Inspect the state that survives between lines

Choose either a two-pass iterator check or a function default argument. Predict what the second operation sees before reading the trace.

Python state pattern

Python code under inspection

records = (n for n in [12, 18, 25])
first_check = any(n >= 18 for n in records)
total = sum(records)
print((first_check, total))
# -> (True, 25)

State trace

any(n >= 18 for n in records) consumes 12 and stops as soon as 18 matches. Because records is a one-shot generator, sum(records) resumes at the remaining element (25) instead of summing all three numbers (55).

Elements consumed during pass 1
[12, 18] → True
Remaining in records before sum(records)
[25]
Final printed tuple vs full sum (55)
(True, 25)

Practice spotting stateful inputs in Python

A helper accepts an iterable of numbers, checks if any value is negative with any(x < 0 for x in items), and then averages items. Which input type breaks the average?

Check the reasoning

Passing a generator or file iterator breaks the second pass because any() advances the iterator through every non-negative item until it stops. If all items are non-negative, the iterator is completely exhausted before the average calculation begins.

This is an original open example, not a scored drill. Close the tool before taking a diagnostic or an unassisted practice session.

About 14 minutes, no account needed. A free account adds a daily practice queue; paid plans add more practice and the full library.

How to use the result

Switch between the two-pass iterator trace and the mutable default argument trace. Change the container or function signature and inspect what state survives into the next operation.

In Python, any(n >= 18 for n in records) consumes 12 and stops when 18 matches. Because records is a generator iterator, sum(records) resumes from the cursor and sums only the remaining 25. Converting the input to a sequence or materializing a list preserves all three items for the second pass.

These utilities and open examples do not contribute to your diagnostic score or practice history.

Python docs: default argument values and iterators

Work through the example

Trace exhausted Python iterators and shared mutable defaults →