Kürzlich schrieb ich eine Funktion, um bestimmte Sequenzen mit nichttrivialen Einschränkungen zu generieren. Das Problem kam mit einer natürlichen rekursiven Lösung. Nun passiert es, dass selbst bei relativ kleinen Eingaben die Sequenzen mehrere Tausend sind. Daher würde ich meinen Algorithmus lieber als Generator verwenden, anstatt ihn zu verwenden, um eine Liste mit allen Sequenzen zu füllen.Python: Verwenden eines rekursiven Algorithmus als Generator
Hier ist ein Beispiel. Angenommen, wir wollen alle Permutationen eines Strings mit einer rekursiven Funktion berechnen. Der folgende naive Algorithmus nimmt ein zusätzliches Argument ‚Lagerung‘ und fügt ihm eine Permutation, wenn es so findet man:
def getPermutations(string, storage, prefix=""):
if len(string) == 1:
storage.append(prefix + string) # <-----
else:
for i in range(len(string)):
getPermutations(string[:i]+string[i+1:], storage, prefix+string[i])
storage = []
getPermutations("abcd", storage)
for permutation in storage: print permutation
(. Bitte um Ineffizienz sich nicht, dies ist nur ein Beispiel)
Jetzt ich möchte, dass meine Funktion in einen Generator drehen, dh eine Permutation zu erhalten, anstatt sie auf der Speicherliste anhängt:
def getPermutations(string, prefix=""):
if len(string) == 1:
yield prefix + string # <-----
else:
for i in range(len(string)):
getPermutations(string[:i]+string[i+1:], prefix+string[i])
for permutation in getPermutations("abcd"):
print permutation
Dieser Code funktioniert nicht Arbeit (die Funktion verhält sich wie ein leerer Generator).
Fehle ich etwas? Gibt es eine Möglichkeit, den obigen rekursiven Algorithmus in einen Generator zu verwandeln, ohne ihn durch einen iterativen zu ersetzen?
In Python 3.4 können Sie die letzten beiden Zeilen mit 'Ausbeute von getPermutations ersetzen (string [: i] + string [i + 1:]) ', was in vielerlei Hinsicht effizienter ist! –
Sie müssten das Ergebnis in irgendeiner Weise noch erstellen. Wenn Sie 'yield from' verwenden, müssen Sie das Akkumulatorargument (' prefix') verwenden. –
Vorschlag: Definieren Sie einen anderen Generator, der 'string [i], string [: i] + string [i + 1:]' Paare zurückgibt. Dann wäre es: 'für Buchstaben, Ruhe in first_letter_options (string): für perm in getPermuations (rest): yield + perm' –