web-dev-qa-db-fra.com

Comment puis-je obtenir les résultats d'une fonction de générateur Python imbriquée?

J'ai une fonction qui donne des résultats à mesure qu'elle les télécharge. Aux fins de cette question, disons que je cède une piqûre une fois par seconde mais je veux une fonction de commodité pour envelopper mon générateur:

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

... pourquoi n'imprimez-vous pas les 5 chaînes que j'attends? Au lieu de cela, il semble retourner la fonction générateur:

<generator object GeneratorFunction at 0x020649B8>

Comment puis-je obtenir ceci pour donner les chaînes comme le ferait une fonction de générateur normale?

27
Jon Cage

Je ne peux pas croire que j'ai raté ça. La réponse est simplement de renvoyer la fonction génératrice avec les arguments appropriés appliqués:

import time

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

def SmallGenerator():
    return GeneratorFunction(3) # <-- note the use of return instead of yield

for s in SmallGenerator():
    print s
19
Jon Cage

Vous devrez peut-être utiliser le nouveau yield from , disponible depuis Python 3.3, connu sous le nom de “ générateur délégué ”.

Si j'ai bien compris la question, je suis arrivé au même problème et j'ai trouvé une réponse ailleurs.

Je voulais faire quelque chose comme ça:

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

J'utilise maintenant ceci à la place:

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

J'ai eu la réponse de cette page: Python 3: Utilisation de "rendement de" dans Generators - Part1 (simeonvisser.com) .

15
Hibou57

Je suis venu ici à la recherche d'une autre forme de "rendement imbriqué" et a finalement trouvé la réponse cachée. Peut-être pas le meilleur mais ça marche. 

Je voulais céder à travers un arbre de registre et voici la solution.

        def genKeys(key):
            for value in key.values():
                yield value
            for subkey in key.subkeys():
                print(subkey)
                for x in genKeys(subkey): #this is the trick
                    continue
1
ben

Voici un autre petit exemple pour générer la table de multiplication de 1 à 10:

class Gen1:

    def __init__(self, gen2):
        self.gen2 = gen2

    def __iter__(self):    
        for a in range(1, 11):    
            for b in self.gen2:
                yield a * b


class Gen2:    

    def __iter__(self):
        for a in range(1, 11):
            yield a


def main():

    gen2 = Gen2()
    gen1 = Gen1(gen2)

    for v in gen1:
        print(v)

if __== '__main__':
    main()
0
displayname

Je suis venu à la recherche d'une autre utilisation des rendements imbriqués ..

list_of_lists = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

def iter_all(foo):
    yield foo

    if isinstance(foo, list):
        for i in foo:
            for x in iter_all(i):
                yield x


print([i for i in iter_all(list_of_lists)])

sortie:

[[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [1, 2, 3], 1, 2, 3, [4, 5, 6], 4, 5, 6, [7, 8, 9], 7, 8, 9]
0
Ben