3

Je suis relativement nouveau en programmation et je travaille avec Python depuis quelques mois maintenant. J'essaie de faire fonctionner un concept avec Stackless, mais je n'arrive pas à comprendre comment (même si j'ai écrit other test scripts qui fonctionne avec Stackless). Anywho, dans un exemple réduit, considère le code suivant qui parcourt une liste et trouve toutes les permutations (édition: produits cartésiens ndimensionnels) en appelant la même fonction récursivement.Stackless Python - Récursion dans une boucle for?

def traverseList(theList,temp,solutions,level=1): 
    if level != len(theList): 
     for x in theList: 
      temp.append(x) 
      traverseList(theList,temp,solutions,level+1) 
      temp.pop() 
    else: 
     for x in theList: 
      temp.append(x) 
      solutions.append(temp[:]) 
      temp.pop() 

myList = ["a",None,2,"gamma",8] #the list doesn't always have just numbers 
solutionList = [] 
tempList = [] 

traverseList(myList,tempList,solutionList) 
print("%s... %s" %(solutionList[0], solutionList[-1])) 

qui donne:

['a', 'a', 'a', 'a', 'a']... [8, 8, 8, 8, 8] 

Jusqu'à présent, il semble que les seuls exemples que je trouve avec Stackless et récursion ont la fonction d'envoi d'informations à la fin de la fonction après tout cela se fait. Jamais au milieu d'une boucle for, comme ce serait nécessaire dans le ci-dessus.

Comment diable ferais-je cela? Comment pourrais-je transformer cela en un script qui fonctionnerait avec des tâches plutôt que des fonctions récursives? (This version est le meilleur que je peux trouver, mais il échoue peu importe comment je l'arrange.C'est un des nombreux essais, je peux aussi bien jeter des spaghettis contre un mur à ce stade.)

Bonus e- cookie pour un moyen de le faire sans une fonction bounceBack - Je n'ai pas encore été en mesure de trouver un moyen d'avoir une seule tâche de transmettre des informations à elle-même plusieurs fois sans un.

Merci pour votre temps!

+2

Je ne connais littéralement rien sur Stackless Python, mais je pense que je devrais faire quelques notes mineures. Premièrement, je déconseille d'utiliser 'main' comme nom de variable. Deuxièmement, ceci ne calcule pas les permutations, il calcule le produit cartésien n-dimensionnel d'une liste d'éléments n. (Il n'y a que 120 permutations d'une liste de 5 éléments.) Troisièmement, [récursion] (http://en.wikipedia.org/wiki/Recursion_ (computer_science)) et [concurrent] (http: //en.wikipedia. org/wiki/Concurrency_ (computer_science)) ne sont pas du tout les mêmes. Désolé je ne peux pas aider avec le problème principal que vous rencontrez! – senderle

+1

Pour l'utilisation de 'main', c'est logique, je vais le garder à l'esprit. Quant au produit cartésien ... Je ne peux pas promettre que je me souviendrai du mot, mais j'essaierai de me souvenir de la différence. Idem pour les différences entre la récursivité et la concurrence. Il est difficile d'avoir tous les mots pour enseigner, mais je ferai de mon mieux. Merci! – squid808

Répondre

1

Je pense que vous voulez rechercher des "générateurs" (c.-à-d. "Rendre" un mot-clé python). Fondamentalement, un générateur vous permet de faire une pause au milieu d'un appel de fonction et sorte de retourner le résultat. Lorsque la fonction est à nouveau appelée, elle reprend à la ligne juste après le "yield". Quand vous "retournez" finalement, vous avez terminé.

Voici quelques exemples de code pour vous:

def myGen(*x): 
    for elem in x: 
    print "in myGen" 
    yield elem 

def myFn(*x): 
    ret = [] 
    for elem in x: 
    print "in myFn" 
    ret.append(x) 
    return x 


for e in myGen(1,2,3,4,5): 
    print e 

for e in myFn(1,2,3,4,5): 
    print e 

La sortie est ci-dessous. Remarquez dans le boîtier du générateur (myGen), le "in myGen" est imprimé en alternance avec l'impression de la liste. Mais dans le myFn bien sûr "in myFn" est imprimé en premier.

in myGen 
1 
in myGen 
2 
in myGen 
3 
in myGen 
4 
in myGen 
5 
in myFn 
in myFn 
in myFn 
in myFn 
in myFn 
1 
2 
3 
4 
5 
+0

J'ai utilisé des générateurs et des rendements, mais je ne vois pas comment cela pourrait m'aider.Oui, un générateur peut faire une pause après un rendement jusqu'à ce qu'il soit appelé à nouveau, mais cela ferait partie du problème. Pour que Stackless puisse à nouveau faire appel à la même tâche, la tâche doit être dans une position libre et d'écoute. Le générateur serait simplement mis en pause et n'accepterait pas vraiment de nouvelles entrées. – squid808

0

Si je comprends bien votre question et puisque vous avez déjà votre méthode en place, brancher ce travaillerais dans

import stackless as s 
channel = s.channel() 
s.tasklet(traverseList)(myList,tempList,solutionList) 
s.run() 
print("%s... %s" %(solutionList[0], solutionList[-1])) 

Sinon, vous pouvez utiliser */** args kwargs dans les paramètres liste à la Tasklet