0

Use Case

I have a variable list of ordered generators that I am trying to chain together. By chain together I mean that I am taking some input and creating generator_1 from that input. Then I get the item_1 from generator_1 and use that to create generator_2.

This continues until I reach the last generator in the list; at which point I exhaust that generator.

Example

I have written this code, which reading it seems to do what I want but it is not functioning correctly:

def run(x):
    functions = [one_produces_three, one_produces_one]

    def recurse(idx, message):
        if idx == len(functions) - 1:
            yield message
        else:
            next_gen = functions[idx + 1](message)
            for next_message in next_gen:
                recurse(idx + 1, next_message)

    return recurse(-1, x)


def one_produces_three(one_input):
    for x in xrange(0, 3):
        print "one produces three %s %s" % (one_input, x)
        yield one_input + x


def one_produces_one(one_input):
    print "one produces one %s" % one_input
    yield one_input


if __name__ == "__main__":
    for r in run(1):
        print r

When I step through this with a debugger, the problem appears to be on line 10: recurse(idx + 1, next_message). For some reason this is a no-op, the recursive call never happens and the one_produces_one method is never called.

This is obvious when I run the code because I only get the output:

one produces three 1 0
one produces three 1 1
one produces three 1 2

The output I would expect would be:

one produces three 1 0
one produces one 1
1
one produces three 1 1
one produces one 2
2
one produces three 1 2
one produces one 3
3

Why is my recursive method call not being invoked?

FGreg
  • 14,110
  • 10
  • 68
  • 110
  • 1
    Your recursive call is invoked just fine, but all it does is make another generator. You don't do anything with the resulting generator. – user2357112 Jul 13 '16 at 22:16
  • If a function *yield* something, it cannot *return* something. Only ``return`` without argument (equivalent to ``raise StopIteration``). See PEP255 ``_. – Laurent LAPORTE Jul 13 '16 at 22:16
  • @user2357112 you're right I just realized that I need to exhaust the recursively created generator. If I change line 10 to `for result in recurse(idx + 1, next_message): yield result` it works. The linked duplicate question pretty much covers my use case so I'll leave it as is. Thanks. – FGreg Jul 13 '16 at 22:21

0 Answers0