I'd like to create a generator factory, i.e. a generator that yields generators, in python using a "generator expression" (generator equivalent of list comprehension). Here's an example:
import itertools as it
gen_factory=((pow(b,a) for a in it.count(1)) for b in it.count(10,10))
In my mind this should give the following output:
((10,100,1000,...), (20,400,8000,...), (30,900,27000,...), ...)
However, the following shows that the internal generators are getting reset:
g0 = next(gen_factory)
next(g0) # 10
next(g0) # 100
g1 = next(gen_factory)
next(g1) # 20
next(g0) # 8000
So the result of the last statement is equal to pow(20,3) whereas I expected it to be pow(10,3). It seems that calling next(gen_factory) alters the b value in g0 (but not the internal state a). Ideally, previous generators shouldn't change as we split off new generators from the generator factory.
Interestingly, I can get correct behavior by converting these to lists, here's a finite example:
finite_gen_factory = ((pow(b,a) for a in (1,2,3)) for b in (10,20,30))
[list(x) for x in finite_gen_factory]
which gives [[10, 100, 1000], [20, 400, 8000], [30, 900, 27000]], but trying to maintain separate generators fails as before:
finite_gen_factory = ((pow(b,a) for a in (1,2,3)) for b in (10,20,30))
g0 = next(finite_gen_factory)
g1 = next(finite_gen_factory)
next(g0) # 20, should be 10.
The closest explanation, I think, is in this answer, but I'm not sure what the correct way of resolving my problem is. I thought of copying (cloning) the internal generators, but I'm not sure this is possible. Also it.tee probably doesn't work here. A workaround might be defining the inner generator as a class, but I really wanted a compact generator expression for this. Also, some stackoverflow answers recommended using functools.partial for this kind of thing but I can't see how I could use that here.