python学习05-协程

1、生成器与协程的关系

从语法上看,协程与生成器类似,都是定义体中包含yield关键字的函数。普通函数将return改为yield就变成生成器函数,生成器函数返回的结果就是生成器
但在协程中,yield通常出现在表达式的右边(如,x = yield),可以产出值,也可以不产出,如果yield关键字后面没有表达式,生成器就产出None
协程可能会从调用方接收数据,不过调用方把数据提供给协程使用的是.send(datum)方法,而不是next()函数,通常调用方会把值推送给协程
不管数据如何流动,yield都是一种流程控制工具,可以实现协作式多任务,协程可以把控制器让步给中心调度程序,从而激活其他的协程

#协程使用生成器函数定义:定义体中有yield关键字
#如下为一个简单的协程
def simple_coroutine():
    print('start')
    x = yield
    print('x:',x)
    print('finish')
my_coro = simple_coroutine()
next(my_coro)#第一次使用,首先需要调用next()方法启动生成器,如果生成器没有启动,没有yield语句处暂停,就无法发送数据

my_coro.send(6)
#生成器使用yield时,只用于返回生成的值,而不会接收值

#协程使用yield时,除了可以返回值,还可以接收值。生成器和协程在定义上很相近,在具体的实现上也是类似的

2、协程的状态

协程可以身处于4个状态中的一个,当前状态可以使用inspect.getgeneratorstate(…)函数确定,该函数会返回下述字符串中的一个。
'GEN_CREATED’等待开始执行
'GEN_RUNNING’解释器正在执行
'GEN_SUSPENDED’在yield处暂停
'GEN_CLOSED’执行结束

def simple_coro(a):
    print('start:a = ',a)
    #返回a的值,获取send()传入的值
    b = yield a
    print('received:b = ',b)
    c = yield a + b
    print('received:c = ',c)
#获得协程对象
my_coro = simple_coro(1)
from inspect import getgeneratorstate
print(getgeneratorstate(my_coro))
#向前执行协程到第一个yield表达式,打印start:a = 14消息后,产出a的值,并且暂停,等待为b赋值
next(my_coro)
print(getgeneratorstate(my_coro))
#把数字2发送给暂停的协程,计算yield表达式,得到2,把那个数绑定给b
#打印received:b = 2消息,产出a + b 的值3,然后协程暂停,等待为c赋值
print(my_coro.send(2))

#使用协程计算移动平均值,原始闭包实现

def make_avg():
    count = 0
    total = 0
    def avg(new_value):
        nonlocal count,total
        count += 1
        total += new_value
        return total / count
    return avg

avg = make_avg()

print(avg(5))
print(avg(6))

def make_avg():
    total = 0
    count = 0
    avg = None
    while True:#无限循环表明,只要调用方法不断把值发给这个协程,它就会一直接收,然后生成结果。
        term = yield avg
        total += term
        count += 1
        avg = total / count

avg_coro = make_avg()
next(avg_coro)
print(avg_coro.send(5))
print(avg_coro.send(6))

#调用next(coro_avg)函数后,协程会向前执行到yield表达式,产出average变量的初始值None,因此不会出现在控制台中
#此时,协程在yield表达式处暂停,等到调用方发送值,激活协程,把发送的值赋给term,更新total、count、average三个变量
#的值,开始while的下一次迭代,产出average变量的值,等待下一次为term变量赋值

#使用装饰器预激活协程

from functools import wraps

def corotine(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        gen = func(*args,**kwargs)
        next(gen)
        return gen
    return wrapper

@corotine
def make_avg():
    total = 0
    count = 0
    avg = None
    while True:#无限循环表明,只要调用方法不断把值发给这个协程,它就会一直接收,然后生成结果。
        term = yield avg
        total += term
        count += 1
        avg = total / count

avg_coro = make_avg()
print(avg_coro.send(5))
print(avg_coro.send(6))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值