En Python sans pile, pouvez-vous envoyer un canal sur un canal?
-
10-07-2019 - |
Question
Je n'ai pas stackless en cours d'exécution, je ne peux donc pas essayer moi-même.
import stackless
ch1 = stackless.channel()
ch2 = stackless.channel()
ch1.send(ch2)
ch3 = ch1.receive()
Les ch2 et ch3 sont-ils le même canal? Dites:
text = "Hallo"
ch2.send(text)
assert text == ch3.receive()
Cette fonctionnalité m'a rappelé un parler de Newsqueak que Robert Pike (de < a href = "http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs" rel = "nofollow noreferrer"> Plan9 ) a été publié sur Google. Dans Newsqueak, vous pouvez envoyer des chaînes par chaîne.
La solution
Oui. Vient de tester.
>>> import stackless
>>> ch1 = stackless.channel()
>>> def a():
... ch2 = stackless.channel()
... ch1.send(ch2)
... ch2.send("Hello")
...
>>> def b():
... ch3 = ch1.receive()
... print ch3.receive()
...
>>> stackless.tasklet(a)()
<stackless.tasklet object at 0x01C6FCB0>
>>> stackless.tasklet(b)()
<stackless.tasklet object at 0x01C6FAB0>
>>> stackless.run()
Hello
Autres conseils
Les canaux envoient des références Python normales afin que les données que vous envoyez (canal, chaîne, peu importe) correspondent exactement à ce qui est reçu.
Un exemple d'envoi d'un canal sur un canal est le cas où vous utilisez un tasklet en tant que service, c'est-à-dire qu'il écoute les demandes sur un canal, fonctionne et renvoie le résultat. La demande doit inclure les données du travail et le canal de retour du résultat pour que le résultat soit transmis au demandeur.
Voici un exemple extrême que j'ai développé pour mon Causerie sans pile chez PyCon il y a quelques années. Cela crée un nouveau tasklet pour chaque appel de fonction afin que je puisse utiliser une implémentation récursive de factorial qui ne doit pas s'inquiéter de la limite de pile de Python. J'attribue un tasklet pour chaque appel et il obtient le canal de retour pour le résultat.
import stackless
def call_wrapper(f, args, kwargs, result_ch):
result_ch.send(f(*args, **kwargs))
# ... should also catch and forward exceptions ...
def call(f, *args, **kwargs):
result_ch = stackless.channel()
stackless.tasklet(call_wrapper)(f, args, kwargs, result_ch)
return result_ch.receive()
def factorial(n):
if n <= 1:
return 1
return n * call(factorial, n-1)
print "5! =", factorial(5)
print "1000! / 998! =", factorial(1000)/factorial(998)
Le résultat est:
5! = 120
1000! / 998! = 999000
J'ai dans ma présentation quelques autres exemples d'envoi de canaux par canaux. C'est une chose courante dans Stackless.