1

Can someone explain the mechanics of why it prints only 3 lines, instead of 24. I know its due to the fact that the generator function is exhausted, but how?

def counter_gen(size):
    cur=1
    while cur <= size:
        yield cur
        cur +=1

c1=counter_gen(8)
c2=counter_gen(3)

for x in c1:
    for y in c2:
        print x,y
Roman
  • 567
  • 3
  • 17
  • if you want a detailed explanation of generators in general, this very topic is the top rated python question on this site: http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained – Free Monica Cellio Aug 19 '13 at 01:02

2 Answers2

5

c2 reaches its end after 3 iterations. Iterating on it again will do nothing. That's what's meant by "exhausting" the iterator. So, after three items, it stops. Your outer iterator goes 8 times, but because the inner iterator only goes 3 times, only the first outer iteration does anything. The next 7 try to iterate over the exhausted iterator, and nothing happens.

If you want a new iteration of c2 to start with each iteration of c1, simply write it that way!

c1=counter_gen(8)

for x in c1:
    c2=counter_gen(3)
    for y in c2:
        print x, y

Or, do away with the c1 and c2 entirely:

for x in counter_gen(8):
    for y in counter_gen(3):
        print x, y
kindall
  • 178,883
  • 35
  • 278
  • 309
  • Oh, how I've completely missed that,and started rationalizing that it must somehow sharing state in a way that was not making sense to me. Thank you, this cleared it up. – Roman Aug 19 '13 at 00:41
1

c1 and c2 are generator objects. You can iterate over them once, then further calls to next() will raise StopIteration. Playing around in an interpreter should give you an idea of what's happening:

>>> c1 = counter_gen(3)
>>> for item in c1:
        pass
>>> c1.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> [i for i in c1]  # Exhausted, will immediately raise StopIteration
[]

Try creating a new generator in the body of the loop instead:

for x in counter_gen(8):
    for y in counter_gen(3):
        print x,y
David Cain
  • 16,484
  • 14
  • 65
  • 75