How to yield results from a nested generator function?

Jon Cage picture Jon Cage · Jun 25, 2012 · Viewed 27.3k times · Source

I have a function which yields results as it downloads them. For the purposes of this question, lets say I yield a sting once every second but I want a convenience function to wrap my generator:

import time

def GeneratorFunction(max_val):
    for i in range(0,5):
        time.sleep(1)
        yield "String %d"%i

def SmallGenerator():
    yield GeneratorFunction(3)

for s in SmallGenerator():
    print s

...why doesn't that just print the 5 strings I'm expecting? Instead it appears to return the generator functio:

<generator object GeneratorFunction at 0x020649B8>

How can I get this to yield the strings as a normal generator function would?

Answer

Hibou57 picture Hibou57 · Sep 5, 2014

You may have to use the new yield from, available since Python 3.3, known as “delegated generator”.

If I understood the question correctly, I came to the same issue, and found an answer elsewhere.

I wanted to do something like this:

def f():

    def g():

        do_something()
        yield x
        …
        yield y

    do_some_other_thing()
    yield a
    …
    g()  # Was not working.
    yield g()  # Was not what was expected neither; yielded None.
    …
    yield b

I now use this instead:

yield from g()  # Now it works, it yields x and Y.

I got the answer from this page: Python 3: Using "yield from" in Generators - Part 1 (simeonvisser.com).