本文共 2800 字,大约阅读时间需要 9 分钟。
历史历程
定义:协程 是为非抢占式多任务产生子程序的计算机程序组件,协程允许不同入口点在不同位置暂停或开始执行程序”。
从技术角度讲,协程就是一个你可以暂停执行的函数,或者干脆把协程理解成生成器
协程的实现:
协程的四个状态
协程终止
yield from
# 协程代码案例1def simple_coroutine(): print('-> start') x = yield print('-> recived', x) yield#主线程sc = simple_coroutine()print(1111)# 可以使用sc.send(None),效果一样next(sc) #预激print(2222)sc.send('zhexiao')
# 案例v2, 协程的状态def simple_coroutine(a): print('-> start') b = yield a print('-> recived', a, b) c = yield a + b print('-> recived', a, b, c)# runcsc = simple_coroutine(5)aa = next(sc)print(aa)bb = sc.send(6) # 5, 6print(bb)cc = sc.send(7) # 5, 6, 7print(cc)
# 案例v03def gen(): for c in 'AB': yield c# list直接用生成器作为参数print(list(gen()))def gen_new(): yield from 'AB'print(list(gen_new()))
# 案例v04, 委派生成器from collections import namedtuple'''解释:1. 外层 for 循环每次迭代会新建一个 grouper 实例,赋值给 coroutine 变量; grouper 是委派生成器。2. 调用 next(coroutine),预激委派生成器 grouper,此时进入 while True 循环,调用子生成器 averager 后,在 yield from 表达式处暂停。3. 内层 for 循环调用 coroutine.send(value),直接把值传给子生成器 averager。同时,当前的 grouper 实例(coroutine)在 yield from 表达式处暂停。4. 内层循环结束后, grouper 实例依旧在 yield from 表达式处暂停,因此, grouper函数定义体中为 results[key] 赋值的语句还没有执行。5. coroutine.send(None) 终止 averager 子生成器,子生成器抛出 StopIteration 异常并将返回的数据包含在异常对象的value中,yield from 可以直接抓取 StopItration 异常并将异常对象的 value 赋值给 results[key]'''ResClass = namedtuple('Res', 'count average')# 子生成器def averager(): total = 0.0 count = 0 average = None while True: term = yield # None是哨兵值 if term is None: break total += term count += 1 average = total / count return ResClass(count, average)# 委派生成器def grouper(storages, key): while True: # 获取averager()返回的值 storages[key] = yield from averager()# 客户端代码def client(): process_data = { 'boys_2': [39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3], 'boys_1': [1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46] } storages = { } for k, v in process_data.items(): # 获得协程 coroutine = grouper(storages, k) # 预激协程 next(coroutine) # 发送数据到协程 for dt in v: coroutine.send(dt) # 终止协程 coroutine.send(None) print(storages)# runclient()
转载地址:http://srba.baihongyu.com/