-2

Consider this Python snippet:

range1 = range(3)
range2 = range(2)
print([(e1, e2) for e1 in range1 for e2 in range2])

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, at the least, inconsistent. This behaviour occurs at least on Python 2.7, 3.12 and 3.14.
Notes:

  1. 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.
  2. From my understanding, the root issue is that outer iter1 stops as soon as inner iter2 stops, which is unexpected.
  3. 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.

4
  • 2
    You can't re-iterate over an iterator, whereas you can over a range. So you consume iter2 while dealing with the first item in iter1. Commented Nov 30 at 20:15
  • 2
    And it works in the inlined list comprehension because you're calling iter(range(2)) again for each item in iter1, so whether or not each one gets exhausted is irrelevant. Commented Nov 30 at 20:20
  • @jonrsharpe Thanks for your quick reply. Ok, I understand the point. I now see that my misunderstanding lay in considering "range" as a special kind of iterator. The difference, as you state it, is now clear. Commented Nov 30 at 20:51
  • 1
    For those interested, note that the function itertools.product allows getting rid of nested for loops, hence avoiding bad surprises. Commented Nov 30 at 21:37

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.