0

I'm trying to make a list comprehension from two generators

g1 = (a for a in range(3))
g2 = (b for b in range(5))
l = [(i, j) for i in g1 for j in g2]
print(l)

but instead of a list of 15 tuples it only returns results of the first inner loop.

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

However, if to put the generators into the comprehension itself, the result is as expected.

l = [(i, j) 
    for i in (a for a in range(3))
    for j in (b for b in range(5))]
print(l)

Do I miss something, or is it just a kind of a "feature"?

Here are cProfile outputs for both versions.

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        4    0.000    0.000    0.000    0.000 t.py:1(<genexpr>)
        1    0.000    0.000    0.000    0.000 t.py:1(<module>)
        6    0.000    0.000    0.000    0.000 t.py:2(<genexpr>)
        1    0.000    0.000    0.000    0.000 t.py:3(<listcomp>)
        1    0.000    0.000    0.000    0.000 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.print}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 t.py:1(<listcomp>)
        1    0.000    0.000    0.000    0.000 t.py:1(<module>)
        4    0.000    0.000    0.000    0.000 t.py:2(<genexpr>)
       18    0.000    0.000    0.000    0.000 t.py:3(<genexpr>)
        1    0.000    0.000    0.000    0.000 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.print}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
N. Mart
  • 3
  • 1

1 Answers1

1

The generator can only be consumed ones. After that it is empty.

In your first example g1 is used for the first item of g2. For each further item of g2 it is already "used up" and returns nothing.

In your second example for each iteration of the outer loop a new fresh generator is created.

Further reading: Resetting generator object in Python

Markus
  • 5,976
  • 5
  • 6
  • 21
  • I see, it's clear now. I paid my attention to the first generator since it looked like the outer loop happened only once, while the reason was the depleted second generator. Thanks =) – N. Mart Oct 28 '22 at 07:30