Search code examples
pythonrecursiongeneratoryield

Python generator to yield everything from another generator call


I have a Python generator that can call itself to get more elements to yield. It looks like this:

def gen(list):
    # ...
    if list:
        for x in gen(list[1:]):
            yield x

My question is about the last two lines: is there a more concise way to express this? I am hoping for something like this (understanding this isn't valid Python as-is):

def gen(list):
    # ...
    if list:
        yield each in gen(list[1:])

Solution

  • Python 3.3 added the yield from keyword. Here's a comparison between what you currently have and code using the new keyword:

    yield_from_test.py:

    def gen_for(a_list):
        if a_list:
            yield a_list[0]
            for x in gen_for(a_list[1:]):
                yield x
    
    def gen_yield(a_list):
        if a_list:
            yield a_list[0]
            yield from gen_yield(a_list[1:])
    
    if __name__ == '__main__':
        assert list(gen_for([1,2,3])) == list(gen_yield([1,2,3]))
        print(list(gen_yield([1,2,3])))
    

    » python3 yield_from_test.py [1, 2, 3]