Python bug when nesting "for" on iterators?

2 weeks ago 13
ARTICLE AD BOX

Consider this Python snippet:

iter1 = range(3) iter2 = range(2) print([(e1, e2) for e1 in iter1 for e2 in iter2])

This displays 3x2 = 6 tuples, as expected:

[(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]

Fine! Now, let's try this slight variant:

iter1 = iter(range(3)) iter2 = iter(range(2)) print([(e1, e2) for e1 in iter1 for e2 in iter2])

The output is surprisingly different:

[(0, 0), (0, 1)]

This result looks wrong or, for the least, inconsistent. This behaviour occurs at least on Python 2.7, 3.12 and 3.14.
Notes:

There are many variants for highlighting the issue, including defining iterators by generators (yield statement). The present description is just the simplest form I've found to highlight the misbehaviour in my code. From my understanding, the root issue is that outer iter1 stops as soon as inner iter2 stops, which is unexpected. The problem does not appear when the iterator objects are instantiated "inline". For example, [(e1, e2) for e1 in iter(range(3)) for e2 in iter(range(2))] returns the 6 expected tuples.

Before opening a Python issue ticket, I'd like to have some feedback on this odd phenomenon, which I consider as a plain bug.

Read Entire Article