2012-06-25 11 views
20

Mam funkcję, która daje wyniki, jak je pobiera. Dla celów tej kwestii, powiedzmy Poddaję żądło raz drugi, ale chcę funkcję wygody owinąć mój generator:Jak uzyskać wyniki z zagnieżdżonej funkcji generatora Pythona?

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 

... dlaczego nie, że po prostu wydrukować 5 strun Jestem przy nadziei? Zamiast tego wydaje się powrót funk prądotwórcze:

<generator object GeneratorFunction at 0x020649B8> 

Jak mogę dostać ten uzyskując struny jako normalnego funkcjonowania generatora chciał?

+7

FYI, w Pythonie 3.3, 'wydajność od GeneratorFunction (3)' zadziała .. – DSM

+0

@DSM: Dzięki . Nadal nie doszło do przejścia na 3+, ale ... –

Odpowiedz

33

SmallGenerator trzeba mieć coś około:

def SmallGenerator(): 
    for item in GeneratorFunction(3): 
     yield item 

W implementacji SmallGenerator daje rzeczywisty generator, a nie przedmioty generowanego przez nią .

+0

Więc dlaczego odpowiedź, którą wysłałem, działa? Ponieważ zwraca generator zamiast go wydobywać? –

+0

@JonCage Tak. Moje wyjaśnienie jest w rzeczywistości błędne. Miałem powiedzieć "zyski", a nie "zwroty". Zmienię to. Zwracanie samego generatora działa (jak w twojej odpowiedzi). Jednak, gdy owijasz generator, chciałbyś zastosować jakąś funkcję dla każdego przedmiotu, który by wygenerował. –

+0

@loan: Tak, widzę to teraz - dzięki za wyjaśnienie. Czy zwrócenie funkcji generatora zamiast pętli i uzyskanie wyniku po raz drugi będzie szybsze? –

15

Nie mogę uwierzyć, że to przegapiłem; Odpowiedź jest po prostu wrócić funkcję generatora z odpowiednimi argumentami stosowane:

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 
10

Być może będziesz musiał użyć new yield from, dostępnego od Pythona 3.3, znanego jako "delegated generator".

Jeśli dobrze zrozumiałem pytanie, doszedłem do tego samego problemu i znalazłem odpowiedź gdzie indziej.

chciałem zrobić coś takiego:

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 

Teraz używam tego zamiast:

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

Dostałem odpowiedź od tej strony: Python 3: Using "yield from" in Generators - Part 1 (simeonvisser.com).

1

Przyjechali tutaj, szukając innej formy "zagnieżdżonego plonu" i wreszcie znaleźli ukrytą odpowiedź. Może nie być najlepszy, ale działa.

Chciałem ustąpić poprzez drzewo rejestru i tutaj jest rozwiązanie.

 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 
0

Oto kolejny mały przykład do generowania tabliczki mnożenia od 1 do 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 __name__ == '__main__': 
    main() 
Powiązane problemy