Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python nested loop with generators does not work (in some cases)?

Would somebody please explain the behavior of a nested loop using generators? Here is an example.

a = (x for x in range(3))
b = (x for x in range(2))
for i in a:
    for j in b:
        print (i,j)

The outer loop is not evaluated after the first iteration for some reason. The result is,

(0, 0)
(0, 1)

On the other hand, if generators are directly inserted into the loops, it does what I expect.

for i in (x for x in range(3)):
    for j in (x for x in range(2)):
        print (i,j)

giving all 3x2 pairs.

(0, 0)
(0, 1)
(1, 0)
(1, 1)
(2, 0)
(2, 1)
like image 201
phantomile Avatar asked Jul 19 '12 21:07

phantomile


2 Answers

It's because the b generator is exhausted during the first iteration of the outer for loop. Subsequent iterations will in effect have an empty inner loop (like for x in ()) so what's inside is never executed. This gives the false impression that it's the outer loop that fails, somehow.

Your second example works because there the inner generator is created anew for each outer loop. To fix your first example, you have to do the same:

a = (x for x in range(3))
for i in a:
    b = (x for x in range(2))
    for j in b:
        print (i,j)
like image 73
Lauritz V. Thaulow Avatar answered Oct 25 '22 17:10

Lauritz V. Thaulow


@lazyr has answered this brilliantly, but I would point out for reference that when using nested generators it's worth knowing about itertools.product...

for i, j in itertools.product(range(3), range(2)):
    print (i, j)

or (if you have lots of vals):

for vals in itertools.product(range(45), range(12), range(3)):
    print (sum(vals))

It's (IMHO) readable and avoids excessive indentation.

like image 24
Jon Clements Avatar answered Oct 25 '22 18:10

Jon Clements