Python 协程的无限递归的问题

发布于 2022-09-01 16:53:26 字数 1231 浏览 9 评论 0

hi, 最近看了关于Python协程的相关文章协程的简单理解,说协程可以无限递归,于是想写一个协程示例练练,于是:

import time


def ping():
    print 'ping 0'
    count = 1
    try:
        pi,po = yield s
        print 'ping ' + str(count)
        count += 1     
        time.sleep(1)
        po.send([po, pi])
    except StopIteration:
        pass


def pong():
    print 'pong 0'
    count = 1
    try:
        po, pi = yield s
        print 'pong ' + str(count)
        count += 1
        time.sleep(1)
        pi.send([pi,po])
    except StopIteration:
        pass


s = ping()
r = pong()
s.next()
r.next()
s.send([s,r])

运行结果是:

ping 0
pong 0
ping 1
pong 1
Traceback (most recent call last):
  File "D:\test\coroutine.py", line 34, in <module>
    s.send([s,r])
  File "D:\test\coroutine.py", line 12, in ping
    po.send([po, pi])
  File "D:\test\coroutine.py", line 25, in pong
    pi.send([pi,po])
ValueError: generator already executing

那篇文章使用了stackless,我想实现一个原始的方法。但是出错,不知道要实现无限递归的话,应该怎么写嘞?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

暗喜 2022-09-08 16:53:26

你需要的是用一个 run 函数管理协程。
在 ping 和 pong 函数内,yield 返回 run。
在 run 函数内,用 next() 对协程进行调度。

import time

def ping():
    print 'ping 0'
    count = 1
    while 1:
        yield po
        print 'ping ' + str(count)
        count += 1
        time.sleep(1)

def pong():
    print 'pong 0'
    count = 1
    while 1:
        yield pi
        print 'pong ' + str(count)
        count += 1
        time.sleep(1)

def run(co):
    while 1:
        co = co.next() # 这行实现 ping 和 pong 交替运行

pi = ping()
po = pong()
pi.next()
po.next()
run(pi)

运行结果:

ping 0
pong 0
ping 1
pong 1
ping 2
pong 2
ping 3
pong 3
ping 4
pong 4
.........

========================================================
带消息传递版:

import time

def ping():
    print 'ping 0'
    count = 1
    while 1:
        msg = yield (po, 'msg from ping')
        print 'ping get', msg
        print 'ping ' + str(count)
        count += 1
        time.sleep(1)

def pong():
    print 'pong 0'
    count = 1
    while 1:
        msg = yield (pi, 'msg from pong')
        print 'pong get', msg
        print 'pong ' + str(count)
        count += 1
        time.sleep(1)

def run(cur, msg='msg from run'):
    while 1:
        cur, msg = cur.send(msg)

pi = ping()
po = pong()
pi.next()
po.next()
run(pi)

运行结果:

ping 0
pong 0
ping get msg from run
ping 1
pong get msg from ping
pong 1
ping get msg from pong
ping 2
pong get msg from ping
pong 2
ping get msg from pong
ping 3
pong get msg from ping
pong 3
ping get msg from pong
ping 4
..............

秋意浓 2022-09-08 16:53:26

你写的确实是有问题,不过最主要的是,Stackless是一个修改版的Python,它的coroutine和标准CPython里的貌似不太一样,如果你想要在CPython里面实现类似的功能,可能需要基于greenlet来做。

尤怨 2022-09-08 16:53:26

http://anandology.com/blog/using-iterators-and-generators/
应该是把generator自身传递造成了问题,send自己导致的
要是pi po是全局变量应该不会有问题

装迷糊 2022-09-08 16:53:26

生成器的用法明显错误,s 没有被 yield 挂起 , 你再去 send/next 当然会报这个错误
不知道你具体是要实现什么, 如果是要 “ping pong” 交替打印, 用一个generator 就行了

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文