В Python без стека вы можете отправить канал по каналу?
У меня в настоящее время нет стека, поэтому я не могу попробовать это сам.
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()
Эта функция напомнила мне разговор о Newsqueak, который Роберт Пайк (известность Plan9) дал в Google. В Newsqueak вы можете отправлять каналы по каналам.
2 ответа
Да. Только что протестировано.
>>> 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
Каналы отправляют обычные ссылки на Python, поэтому отправляемые вами данные (канал, строка и т. Д.) В точности соответствуют полученным.
Одним из примеров отправки канала по каналу является случай, когда вы используете тасклет в качестве службы, то есть тасклет прослушивает запросы на канале, работает и возвращает результат. Запрос должен включать данные для работы и обратный канал для результата, чтобы результат отправлялся запрашивающей стороне.
Вот крайний пример, который я разработал для своего выступления в Stackless на PyCon несколько лет назад. Это создает новый тасклет для каждого вызова функции, так что я могу использовать рекурсивную реализацию факториала, которому не нужно беспокоиться об ограничении стека Python. Я выделяю тасклет для каждого вызова, и он получает обратный канал для результата.
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.