2009-03-12 4 views
4

Ich habe stackless derzeit läuft, so kann ich das nicht selbst ausprobieren.In stackless Python, können Sie einen Kanal über einen Kanal senden?

import stackless 
ch1 = stackless.channel() 
ch2 = stackless.channel() 

ch1.send(ch2) 
ch3 = ch1.receive() 

Sind ch2 und ch3 dann den gleichen Kanal? Sprich:

text = "Hallo" 
ch2.send(text) 
assert text == ch3.receive() 

Diese Funktion erinnerte mich an einen talk about Newsqueak, die Robert Pike (von Plan9 Ruhm) bei Google gab. In Newsqueak können Sie Kanäle über Kanäle senden.

+0

Komisch das würde kommen, ich dachte die genaue Sache über Stackless und wie ich liebe, dass es Kanäle wie Go/Newsqueak haben. – Jyaan

Antwort

4

Ja. Nur getestet.

>>> 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 
3

Kanäle normale Python Referenzen, so dass die Daten senden Sie senden (Kanal, Bindfaden, was auch immer) ist genau das, was empfangen wird.

Ein Beispiel für das Senden eines Kanals über einen Kanal ist, wenn Sie ein Tasklet als Dienst verwenden, dh ein Tasklet hört auf einem Kanal nach Anforderungen ab, funktioniert und gibt das Ergebnis zurück. Die Anforderung muss die Daten für die Arbeit und den Rückkanal für das Ergebnis enthalten, damit das Ergebnis an den Anforderer gesendet wird.

Hier ist ein extremes Beispiel, das ich vor ein paar Jahren für meine Stackless talk at PyCon entwickelt habe. Dadurch wird für jeden Funktionsaufruf ein neues Tasklet erstellt, sodass ich eine rekursive Implementierung von factorial verwenden kann, die sich nicht um Pythons Stack-Limit kümmern muss. Ich weise für jeden Anruf ein Tasklet zu und es erhält den Rückkanal für das Ergebnis.

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) 

Die Ausgabe lautet:

5! = 120 
1000!/998! = 999000 

Ich habe ein paar weitere Beispiele für Kanäle über Kanäle in meiner Präsentation zu senden. Es ist eine gemeinsame Sache in Stackless.

Verwandte Themen