Search code examples
pythongeneratorpython-itertoolsyield

How to get two synchronised generators from a function


i have a nested tuple like this one :

this_one = (w,h,(1,2,4,8,16),(0,2,3,4,6),("0"),("0"),(0,1))

It will be used to feed: itertools.product(*this_one)

w and h have to be both generators.

Generated values from h depends on generated values from w as in this function:

def This_Function(maxvalue):

   for i in range(maxvalue):
       w_must_generate = i
       for j in range(i+1):
           h_must_generate = j         

Iv tried using a yield in This_function(maxvalue):

def This_Function(maxvalue):

   for i in range(maxvalue):
       for j in range(i+1):
           yield i,j

Returning a single generator object which gives:


which_gives = itertools.product(*this_one)
for result in which_gives:
    print(result)
...
((23,22),(16),(6),(0),(0),(0))
((23,22),(16),(6),(0),(0),(1))
((23,23),(1),(0),(0),(0),(0))
...

A single tuple at result[0] holding 2 values.

And this is not what i want .

The result i want has to be like the following:

the_following = itertools.product(*this_one)
for result in the_following:
    print(result)
...
((23),(22),(16),(6),(0),(0),(0))
((23),(22),(16),(6),(0),(0),(1))
((23),(23),(1),(0),(0),(0),(0))
...

Without having to do something like :

the_following = itertools.product(*this_one)
for result in the_following:
    something_like = tuple(result[0][0],result[0][1],result[1],...,result[5])
    print(something_like)
...
((23),(22),(16),(6),(0),(0),(0))
((23),(22),(16),(6),(0),(0),(1))
((23),(23),(1),(0),(0),(0),(0))
...

Any ideas ?


Solution

  • That's fundamentally not how product works. From the documentation:

    Before product() runs, it completely consumes the input iterables, keeping pools of values in memory to generate the products. Accordingly, it is only useful with finite inputs.

    Thus, having the second one be dependent won't get you the result you want, assuming that is for h values to always be w+1..max in the resulting output sequence.

    I'm not sure why you couldn't just run it with your This_function approach and destructure it with a generator expression:

    result = ((a, b, c, d, e, f, g) 
              for ((a, b), c, d, e, f, g) in itertools.product(*this_one))