在无堆栈Python中,您可以通过频道发送频道吗?

时间:2009-03-12 12:46:58

标签: python stackless python-stackless

我目前没有 stackless ,所以我不能自己试试。

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

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

ch2 ch3 那么是同一个频道吗?说:

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

此功能让我想起了罗伯特派克(talk about Newsqueak成名)给予谷歌的Plan9。在Newsqueak,你可以通过频道发送频道。

2 个答案:

答案 0 :(得分:4)

是。刚刚测试过。

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

答案 1 :(得分:3)

频道会发送普通的Python引用,因此您发送的数据(频道,字符串等等)就是收到的数据。

通过通道发送通道的一个示例是当您将tasklet用作服务时,即,tasklet在通道上侦听请求,确实有效并返回结果。请求需要包含工作数据和结果的返回通道,以便结果发送给请求者。

这是我几年前为Stackless talk at PyCon开发的一个极端例子。这为每个函数调用创建了一个新的tasklet,因此我可以使用factorial的递归实现,而不需要担心Python的堆栈限制。我为每个调用分配一个tasklet,它获得结果的返回通道。

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)

输出结果为:

5! = 120 
1000! / 998! = 999000

我还有一些在演示文稿中通过频道发送频道的示例。这在Stackless中很常见。