I am trying to smooth out a nested generator generator, but I get an unexpected result:
>>> g = ((3*i + j for j in range(3)) for i in range(3)) >>> list(itertools.chain(*g)) [6, 7, 8, 6, 7, 8, 6, 7, 8]
I expected the result to look like this:
[0, 1, 2, 3, 4, 5, 6, 7, 8]
I think I get an unexpected result, because the internal generators are not evaluated until the external generator is repeated, setting i
to 2. I can crack the solution by forcing the evaluation of internal generators using a list expression instead of a generator expression:
>>> g = ([3*i + j for j in range(3)] for i in range(3)) >>> list(itertools.chain(*g)) [0, 1, 2, 3, 4, 5, 6, 7, 8]
Ideally, I would like the solution to be completely lazy and not forcibly evaluate internal nested elements until they are used.
Is there a way to smooth out nested expressions of a generator of arbitrary depth (possibly using something other than itertools.chain
)?
Edit:
No, my question is not a duplicate of Variable Scope In Generators In Classes . I honestly cannot say how these two issues are related at all. Maybe the moderator could explain why he thinks this is a duplicate.
In addition, both answers to my question are correct in that they can be used to write a function that correctly aligns nested generators.
def flattened1(iterable): iter1, iter2 = itertools.tee(iterable) if isinstance(next(iter1), collections.Iterable): return flattened1(x for y in iter2 for x in y) else: return iter2 def flattened2(iterable): iter1, iter2 = itertools.tee(iterable) if isinstance(next(iter1), collections.Iterable): return flattened2(itertools.chain.from_iterable(iter2)) else: return iter2
As far as I can tell with timeit
, they both execute the same way.
>>> timeit(test1, setup1, number=1000000) 18.173431718023494 >>> timeit(test2, setup2, number=1000000) 17.854709611972794
I'm not sure which one is better in terms of style, since x for y in iter2 for x in y
is a bit of a brain twister, but maybe more elegant than itertools.chain.from_iterable(iter2)
. Entrance is appreciated.
Unfortunately, I could only point out one of two equally good answers.