python 让协程返回值

下面示例 是 averager 协程的不同版本,这一版会返回结果。为了说明如何返回值每次激活协程不会产出移动平均值。这么做是为了强调某些协程不会产出值,而是在最后返回一个值(通常是某种累计值)

"""
让协程返回值

"""
from collections import namedtuple


Result = namedtuple('Result', 'count average')


def averager():
    total = 0.0
    count = 0
    average = None
    while True:
        term = yield
        if term is None:
            # 为了返回值,协程必须正常终止;因此,这一版 averager 中有个条件判断,以便退出
            # 累计循环。
            break
        total += term
        count += 1
        average = total / count

    # 返回一个 namedtuple,包含 count 和 average 两个字段。在 Python 3.3 之前,如果生成
    # 器返回值,解释器会报句法错误。
    return Result(count, average)


if __name__ == '__main__':
    coro_avg = averager()
    next(coro_avg)

    coro_avg.send(10)  # 这一版不产出值。
    coro_avg.send(30)
    coro_avg.send(40)
    coro_avg.send(80)
    coro_avg.send(10.5)

    try:
        # 发送 None 会终止循环,导致协程结束,返回结果。一如既往,生成器对象会抛出
        # StopIteration 异常。异常对象的 value 属性保存着返回的值。
        coro_avg.send(None)
    except StopIteration as e:
        result = e.value
        print(result)
        # Result(count=5, average=34.1)

获取协程返回值虽然要绕个圈子,但这是 PEP 380 定义的方式,当我们意识到这一点之后就说得通了:yield from 结构会在内部自动捕获 StopIteration 异常。这种处理方式与for 循环处理 StopIteration 异常的方式一样:循环机制使用用户易于理解的方式处理异常。对 yield from 结构来说,解释器不仅会捕获 StopIteration 异常,还会把 value 属性 的值变成 yield from 表达式的值。可惜,我们无法在控制台中使用交互的方式测试这种行为,因为在函数外部使用 yield from(以及 yield)会导致句法出错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值