《流畅的Python》第十六章学习笔记


协程的四个状态

使用inspect.getgeneratirstat()获取协程的状态

等待开始执行

GEN_CREATED

解释器正在执行

GEN_RUNNING

在yield表达式处暂停

GEN_SUPENDED

执行结束

GEN_CLOSED

使用协程计算平均值

def averager():
    total = 0.0
    count = 0
    average = None
    while True:
        term = yield average
        total += term
        count += 1
        average = total / count


if __name__ == '__main__':
    c = averager()
    next(c) # 预激
    print(c.send(10))
    print(c.send(20))
    print(c.send(30))
    print(c.send(5))

协程的终止与异常处理

class DemoException(Exception):
    pass


def demo():
    print('协程开始')
    try:
        while True:
            try:
                x = yield
            except DemoException:
                print('已知异常DemoException')
            else:
                print(f"输入了:{x}")
    finally:
        print('协程结束')


if __name__ == '__main__':
    d = demo()
    next(d)
    d.send(10)
    d.send(11)
    d.throw(DemoException)
    print('1234')
    d.close()

yield from

Yield from 的主要功能是打开双向通道,把最外层的调用方与最内层的子生成器连接起来,这样两者可以直接发送和产出值,还可以直接传出异常,而不用在位于中间的协程中添加大量处理异常的样板代码。

委派生成器

包含yield from <iterable>表达式的生成器函数

子生成器

yield from 表达式中<iterable>部分获取的生成器

调用方

指代委派生成器的客户端代码

例子

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:
            break
        total += term
        count += 1
        average = total / count
    return Result(count, average)


# 委派生成器
def grouper(results, key):
    while True:
        results[key] = yield from averager()


# 客户端代码,调用方
def main(data):
    results = {}
    for key, values in data.items():
        group = grouper(results, key)
        next(group)
        for value in values:
            group.send(value)
        group.send(None)
    report(results)


# 输出报告
def report(results):
    for key, result in sorted(results.items()):
        group, unit = key.split(';')
        print(f'{result.count:2} {group:5} averaging {result.average:.2f}{unit}')


data = {
    'girls;kg': [40.9, 38.5],
    'girls;m': [1.6, 1.51],
    'boys;kg': [39.9, 38.5],
    'boys;m': [1.5, 1.46],
}
if __name__ == '__main__':
    main(data)

输出:

 2 boys  averaging 39.20kg
 2 boys  averaging 1.48m
 2 girls averaging 39.70kg
 2 girls averaging 1.56m
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值