2016-05-01 17 views
1

Ich bin neu bei Generatoren. Warum wird die erste richtige Funktion mit einem Druck Anweisung funktioniert nicht, wenn ich ersetzen den Druck mit Ausbeute (Python 2.7)Generator verhält sich nicht wie erwartet

Zuerst wird die korrekte Funktion mit Druck:

def make_all_pairs(list_): 
    pivot = list_.pop(0) 
    for el in list_: 
     pair = (pivot, el) 
     print pair 
    if len(list_) > 1: 
     make_all_pairs(list_)  

make_all_pairs(["a","b","c","d","e"]) 

('a', 'b') 
('a', 'c') 
('a', 'd') 
('a', 'e') 
('b', 'c') 
('b', 'd') 
('b', 'e') 
('c', 'd') 
('c', 'e') 
('d', 'e') 

Dann der Generator, der nicht alle Kombinationen liefert

def make_all_pairs(list_): 
    pivot = list_.pop(0) 
    for el in list_: 
     pair = (pivot, el) 
     yield pair 
    if len(list_) > 1: 
     make_all_pairs(list_) 

x = make_all_pairs(["a","b","c","d","e"]) 
for el in x: 
    print el 

('a', 'b') 
('a', 'c') 
('a', 'd') 
('a', 'e') 
+0

Danke für die Antworten verwenden Konstrukt! – TomKivy

Antwort

3

Wenn Sie Rekursion verwenden, müssen Sie das Ergebnis erneut liefern.

def make_all_pairs(list_): 
    pivot = list_.pop(0) 
    for el in list_: 
     pair = (pivot, el) 
     yield pair 
    if len(list_) > 1: 
     for pair in make_all_pairs(list_): 
      yield pair 

Erleichtert wird dies in Python 3.X, wo man yield from Iterables anstatt Schleife.

3

Ändern Sie die letzten beiden Zeilen des Generatorfunktion

if len(list_) > 1: 
    make_all_pairs(list_) 

zu

if len(list_) > 1: 
    for pair in make_all_pairs(list_): 
     yield pair 

Während Ihre Druckfunktion nicht zurück oder etwas nachgeben, Sie es einfach rekursiv aufrufen können. Bei einer rekursiven Funktion, die zurückkehrt oder ergibt, müssen diese Werte jedoch aus der Rekursion heraus zurückgegeben, also zurückgegeben oder hier zurückgegeben werden.

1

Die Antwort in Python 2.7 ist nicht groß:

def make_all_pairs(list_): 
    pivot = list_.pop(0) 
    for el in list_: 
     pair = (pivot, el) 
     yield pair 
    if len(list_) > 1: 
     for pair in make_all_pairs(list_): 
      yield pair 


x = make_all_pairs(["a","b","c","d","e"]) 
for el in x: 
    print el 

In Python 3.3 und höher können Sie Ausbeute benutzen stattdessen

5

Während print Drucke von welcher Verschachtelung von Anrufen Sie sind, Generatoren liefern nur von der ersten Ebene. Wenn Sie auf „Anruf-Generator“ müssen mehr Werte erhalten zu erhalten, müssen Sie die Werte aus dem inneren Generator verbrauchen und sie ergeben sich wie folgt dar:

def make_all_pairs(list_): 
    pivot = list_.pop(0) 
    for el in list_: 
     pair = (pivot, el) 
     yield pair 
    if len(list_) > 1: 
     for itm in make_all_pairs(list_): 
      yield pair 

x = make_all_pairs(["a","b","c","d","e"]) 
for el in x: 
    print el 

Achtung: Während der Code liefert nun mehr Werte, I keine Garantie, das Ergebnis ist korrekt. Der Code zeigt nur, wie man mit Werten arbeitet, die vom inneren Generator erzeugt werden.

Hinweis: In Python 3 Sie Alternative kann yield from

def make_all_pairs(list_): 
    pivot = list_.pop(0) 
    for el in list_: 
     pair = (pivot, el) 
     yield pair 
    if len(list_) > 1: 
     yield from make_all_pairs(list_) 
+0

Also ist es eine schlechte Idee, Rekursion in Generatoren zu verwenden? – TomKivy

+2

@TomKivy Nein, verschachtelte Generatoren sind in Ordnung, müssen nur richtig gehandhabt werden (und es ist keine Magie, sobald Sie es bekommen). –

Verwandte Themen