python基础-协程与yield表达式

协程与yield表达式

函数内,yield语句还可以用作出现在赋值运算符右边的表达式, 例如

def receiver():
    print("ready to receive")
    while True:
        n = (yield)
        print("got %s" % n)

以这种方式使用yield语句的函数被称为协程, 它的执行是为了响应发送给它的值。它的行为也十分类似于生成器, 例如:

协程实例

注意,对next()的调用是必不可少的,这样协程才能执行可通向第一个yield表达式的语句。

在这里协程会挂起,等待相关生成器对象r的send()方法给它发送一个值。传递给send()的值有协程中的(yield)表达式返回。接收到值后,协程就会执行语句,直至遇到下一条yield语句。

在协程中需要首先调用next()这件事情很容易被忽略,经常成为错误出现的根源。因此,建议使用一个能自动完成该步骤的装饰器来包装协程。

def coroutine(func):
    def start(*args, **kwargs):
        g = func(*args, **kwargs)
        g.__next__()
        return g
    return start

使用这个装饰器就可以像下面这样编写和使用协程

@coroutine
def receiver():
    print("ready to receive")
    while True:
        n = (yield)
        print("got %s" % n)

# 用例
r = receiver()
r.send("99")    # 注意: 无需初始调用__next__()方法

协程的运行一班是无期限的,除非它被显示关闭或者自己退出。使用方法close()可以关闭输入值的流,例如:

r.close()
r.send(3)   # 此时就会抛出StopIteration异常

关闭后,如果继续给协程发送值,就会引发StopIteration异常。

如果yield表达式中提供了值,协程可以使用yield语句同时接收和发出返回值,例如:

def coroutine(func):
    def start(*args, **kwargs):
        g = func(*args, **kwargs)
        g.__next__()
        return g
    return start

@coroutine
def line_splitter(delimiter = None):
    print("ready to split")
    while True:
        result = None
        line = (yield result)
        result = line.split(delimiter)
        print(result)
        
if __name__ == '__main__':
    s= line_splitter(',')
    s.send('a,b,c')

理解这个例子的先后顺序至关重要。首个next()调用让协程向前执行到了yield(result), 这将返回result的初始值None.在接下来的send()调用中,接收到的值被放在line中并拆分到result中。send()方法的返回值就是传递给下一条yield语句的值。

如果协程返回值,对使用throw()引发的异常进行处理时需要当心。如果使用throw()在协程中引发一个异常,传递给协程中下一条yield语句的值将作为throw()方法的结果返回。如果需要这个值却又忘记保存它,它就会消失不见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

smart_cat

你的鼓励将是我写作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值