Search code examples
python-3.xgeneratoryield

Python 3 generator expression


def gen_letters(s,l):
    def __gen(s,l):
    if l > 1:
        for c in 'abcdefghijklmnopqrstuvwxyz ':
            __gen(s+c,l-1)
    else:
        print(1)
        for c in 'abcdefghijklmnopqrstuvwxyz ':
            yield s+c
    return __gen(s,l)

I am trying to generate all combinations of letters in the alphabet of length "l". The intended use for this functions is:

combos = gen_letters('', 10)

The second argument being the length of the combinations to return. For instance, if I wanted to generate all possible 3 char length strings from the alphabet and a space, I should get 19683 combinations. When trying to use "next(combos)" or "for combo in combos:" (even on the first next()) I get this error:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

Help is much appreciated :)


Solution

  • No need for nested functions and your base case can be even simpler:

    def gen_letters(l):
        if not l:
            yield ""
        else:
            for c in 'abcdefghijklmnopqrstuvwxyz ':
                for combo in gen_letters(l-1):
                    yield c + combo
    
    
        
    [*gen_letters(2)]
    # ['aa', 'ab', ..., ' x', ' y', ' z', '  ']
    

    Or, closer to your original:

    def gen_letters(s,l):
        if l:
            for c in 'abcdefghijklmnopqrstuvwxyz ':
                yield from gen_letters(s+c,l-1)
        else:
            yield s
    
    [*gen_letters('', 2)]
    # ['aa', 'ab', ..., ' x', ' y', ' z', '  ']
    

    Notice the yield from line. This is where you did the correct recursive call, but did not do anything with the result.