Python中的协程能否yield值?

3
我了解生成器和协程的工作原理。广义上讲,生成器生成数据而协程消耗数据。现在,我想要将这两个特性结合起来。
我定义了一个协程,它接收一个列表作为输入,然后尝试像生成器一样逐个**yield**列表中的项。
以下是我的代码 -
def coroutine():
    print('Starting coroutine')
    value = (yield)
    for i in value:
        yield i



c=coroutine()
c.__next__()
c.send([1,2,3,4,5])


for val in c:
    print(val)

问题在于,第一个列表项丢失了。协程没有返回value 1
根据我的理解,流程应该如下:
  1. c=coroutine() ----> 声明coroutine但不启动。
  2. c.__next__() ----> 启动coroutine并前进到value = (yield),停在那里。
  3. c.send([1,2,3,4,5]) ----> 将新的list传递给等待的coroutinevalue = (yield)。协程现在继续执行for循环中下一个yield语句。
  4. 主程序中的for循环应该接收最初传递的列表的每个项。但这没有发生。
请问为什么?我试图生成一个pipeline。每个组件将接收项,修改它,然后将其yield给管道中的下一个协程。
请帮忙解释一下。 编辑 -------------------- 输出结果如下:
Starting coroutine
2
3
4
5
1个回答

2
你漏掉了一个重要的点,即在调用 send 时,协程将一直执行到下一个 yield 并调用它。因此,如果你这样做:
c=coroutine()
c.__next__()
print(c.send([1,2,3,4,5]))


for val in c:
    print(val)

您将看到缺失的值如何被打印(因为它在`send`调用中被产生)。
这里有一个实时示例
对于您想要的行为,您可以向协程添加额外的`yield`语句。
def coroutine():
    print('Starting coroutine')
    value = (yield)
    yield
    for i in value:
        yield i

为什么它要这样工作?第二个yield语句不是等待在调用函数中请求该值吗?c.send(..)只是将协程推进到下一个yield语句,并在那里等待被调用。我问这个问题是因为生成器就是这样工作的,对吧? - undefined
@BoudhayanDev,当协程执行到yield语句时会暂停。而且,一个返回值的yield和一个不返回值的yield是不同的。这就是Python中它们的工作原理。你可以随时添加额外的yield来等待迭代中的下一次调用,并获得你所期望的行为。 - undefined
所以,你的意思是,一个应该返回值的yield语句会被执行,然后协程/生成器暂停,而不是相反,也就是说,一旦协程/生成器遇到返回的yield语句而没有执行它,就会暂停? - undefined
协程一旦遇到yield语句就会暂停,但是在返回某个值的yield语句中,调用next函数会使其继续执行,而等待某个值的协程则需要调用send函数来继续执行。 - undefined
我理解了next方法和send方法之间的区别,以及接收yield和返回yield的方式。我想要弄清楚的是,在执行返回yield语句之后是否会发生暂停,还是在执行返回yield之前发生暂停(在这种情况下,假设一旦获取生成器的值就会执行)。 - undefined
1
@BoudhayanDev 所以,首先yield(等待一个值)-> 调用send -> 推进直到下一个yield(协程将再次等待)yield i 所以它产生了那个值,下一次迭代推进直到下一个yield,即下一个yield i,依此类推。所以,是的,在获取值之后才会执行。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接