小知识:协程

287 阅读2分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

Python中的生成器其实远远不止生成器这么简单。

先前我们使用了生成器和生成器表达式。然后可以让生成器多次产出值交由我们使用。但Python的生成器中还有一个非常中要的函数:send。

在这里我们不再把生成器函数称之为生成器,而是协程了。

send函数可以让我们的程序不再仅仅接受协程产生的值,还能将值发送到协程中。也就是说,我们的程序和协程之间可以相互交互。

具体来说send函数可以传入一个参数,这个参数会成为yield表达式的值。通过在协程中读取yield语句的值,可以获取

假设我们需要写一个程序,用于计算统计输入的奇数和偶数的数量。使用协程来实现

def count():
    even = 0
    odd = 0
    while True:
        cur = yield even, odd
        if cur % 2 == 0:
            even += 1
        else:
            odd += 1

当我们尝试把代码写了就会发现,有哪里不对劲,为什么先前可以使用next?send能不能直接使用?我们在纯粹把这个东西作为生成器的时候是根本就没关注过这些。

情况是这样的,先前在使用next函数的时候,会被当作发送了None值给生成器。现在我们使用send则可以直接从send函数的返回值中获取数据,而不会再使用next函数。

不过呢,像上面写的这个生成器,如果我们直接使用send函数是会报错的。因为send函数的效果是把值交给yield表达式,而函数最开始不是处于yield表达式的位置。

所以这里需要一个关键的操作,在创建函数的时候,使用一次next函数,让函数暂停到yield表达式的位置,之后才可以使用send。这个过程一般被称为预激活。

所以我们使用协程可以像下面这样:

    corutine = count() 
    next(corutine)
    while True:
        x = int(input())
        print(corutine.send(x))

至此,我们完成了协程的使用。