Récemment j'ai écrit une fonction pour générer certaines séquences avec des contraintes non triviaux. Le problème est venu avec une solution récursive naturelle. Maintenant, il arrive que, même pour une entrée relativement petite, les séquences sont plusieurs milliers, donc je préférerais utiliser mon algorithme comme générateur au lieu de l'utiliser pour remplir une liste avec toutes les séquences.Python: en utilisant un algorithme récursif comme un générateur
Voici un exemple. Supposons que nous voulions calculer toutes les permutations d'une chaîne avec une fonction récursive. L'algorithme naïf suivant prend un « stockage » argument supplémentaire et une permutation ajoute chaque fois qu'il en trouve un:
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
(. S'il vous plaît ne se soucient pas de l'inefficacité, ce n'est un exemple)
maintenant Je veux tourner ma fonction dans un générateur, soit pour donner une permutation au lieu d'ajouter à la liste de stockage:
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
Ce code ne pas travail (la fonction se comporte comme un générateur vide).
Ai-je raté quelque chose? Y at-il un moyen de transformer l'algorithme récursif ci-dessus dans un générateur sans le remplacer par un itérative un?
En Python 3.4, vous pouvez remplacer les deux dernières lignes avec 'rendement de getPermutations (string [: i] + string [i + 1:]) ', ce qui est plus efficace à bien des égards! –
Vous auriez encore besoin de construire le résultat d'une manière ou d'une autre. Utiliser 'yield from' vous obligerait à utiliser l'argument accumulateur (' prefix'). –
Suggestion: Définissez un autre générateur qui renvoie les paires 'chaîne [i], chaîne [: i] + chaîne [i + 1:]'. Alors ce serait: 'pour la lettre, reste dans first_letter_options (string): pour perm dans getPermuations (reste): yield lettre + perm' –