-1

Why do these two loops not give the same result? (Yes, I know the second version is bad style. But I'd still expect it to give the same output.)

gen1 = range(3)
gen2 = range(3)
print("First attempt")
for i in gen1:
  for j in gen2:
    print(i,j)

gen1 = (i for i in range(3))
gen2 = (i for i in range(3))
print("Second attempt")
for i in gen1:
  for j in gen2:
    print(i,j)

Output using Python 3.6.9 (and I get the same results with Python 2.7.15):

First attempt
(0, 0)
(0, 1)
(0, 2)
(1, 0)
(1, 1)
(1, 2)
(2, 0)
(2, 1)
(2, 2)
Second attempt
(0, 0)
(0, 1)
(0, 2)
Alexander Hanysz
  • 791
  • 5
  • 15

1 Answers1

4

range is its own type. It’s iterable, but not an iterator (or generator) – you can iterate over it multiple times, each time creating independent iterators:

>>> r = range(2)
>>> list(r)
[0, 1]
>>> list(r)
[0, 1]
>>> next(r)
TypeError: 'range' object is not an iterator

Generators, like from generator expressions, are iterators. When you iterate over them, you advance them.

>>> r = (1 + x for x in range(2))
>>> list(r)
[1, 2]
>>> list(r)
[]
>>> r = (1 + x for x in range(2))
>>> iter(r) is r
True
>>> next(r)
1

And, to answer the first question explicitly, this behaviour isn’t related to interning. During the first iteration of the for i in gen1 loop, gen2 is consumed, so the remaining iterations do nothing.

Ry-
  • 218,210
  • 55
  • 464
  • 476