In Python stackless, puoi inviare un canale su un canale?
-
10-07-2019 - |
Domanda
Non ho stackless attualmente in esecuzione, quindi non posso provarlo da solo.
import stackless
ch1 = stackless.channel()
ch2 = stackless.channel()
ch1.send(ch2)
ch3 = ch1.receive()
ch2 e ch3 sono quindi lo stesso canale? Di ':
text = "Hallo"
ch2.send(text)
assert text == ch3.receive()
Questa funzione mi ha ricordato un parlare di Newsqueak che Robert Pike (di < a href = "http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs" rel = "nofollow noreferrer"> Plan9 fama) dato a Google. In Newsqueak puoi inviare canali su canali.
Soluzione
Sì. Appena testato.
>>> 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
Altri suggerimenti
I canali inviano normali riferimenti Python in modo che i dati inviati (canale, stringa, qualunque cosa) siano esattamente ciò che viene ricevuto.
Un esempio di invio di un canale su un canale è quando si utilizza un tasklet come servizio, ovvero un tasklet è in ascolto su un canale per richieste, funziona e restituisce il risultato. La richiesta deve includere i dati per il lavoro e il canale di ritorno per il risultato, in modo che il risultato vada al richiedente.
Ecco un esempio estremo che ho sviluppato per il mio Discorsi stackless al PyCon alcuni anni fa. Questo crea un nuovo tasklet per ogni chiamata di funzione in modo che io possa usare un'implementazione ricorsiva di fattoriale che non deve preoccuparsi del limite di stack di Python. Allocare un tasklet per ogni chiamata e ottiene il canale di ritorno per il risultato.
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)
L'output è:
5! = 120
1000! / 998! = 999000
Ho alcuni altri esempi di invio di canali su canali nella mia presentazione. È una cosa comune in Stackless.