Recursion using yield

juliomalegria picture juliomalegria · Jan 24, 2012 · Viewed 34.2k times · Source

Is there any way to mix recursion and the yield statement? For instance, a infinite number generator (using recursion) would be something like:

def infinity(start):
    yield start
    # recursion here ...

>>> it = infinity(1)
>>> next(it)
1
>>> next(it)
2

I tried:

def infinity(start):
    yield start
    infinity(start + 1)

and

def infinity(start):
    yield start
    yield infinity(start + 1)

But none of them did what I want, the first one stopped after it yielded start and the second one yielded start, then the generator and then stopped.

NOTE: Please, I know you can do this using a while-loop:

def infinity(start):
    while True:
        yield start
        start += 1

I just want to know if this can be done recursively.

Answer

Sven Marnach picture Sven Marnach · Jan 24, 2012

Yes, you can do this:

def infinity(start):
    yield start
    for x in infinity(start + 1):
        yield x

This will error out once the maximum recursion depth is reached, though.

Starting from Python 3.3, you'll be able to use

def infinity(start):
    yield start
    yield from infinity(start + 1)

If you just call your generator function recursively without looping over it or yield from-ing it, all you do is build a new generator, without actually running the function body or yielding anything.

See PEP 380 for further details.