协程
协程(coroutine),协程是指一个过程,这个过程与调用方协作,产出由调用方提供的值。可以通过关键词yield实现,yield是在协程中是一种流程控制工具。和生成器函数相似,但只是看上去相似。此文主要介绍用python实现协程,异步编程。
一个例子:
从上图的例子可以看出yield 左边的变量的值是由 调用方传入的值,但是一开始不清楚协程的话,很容易因为=这个赋值操作以为左边的值是右边表达式产生的值 。(协程使用前得预激即那一步next(j).让协程向前执行到第一个yield语句,准备好作为活跃的协程使用)
- g = j.send(20),将传入值20赋值给本yield语句(x = yield a + 3)的左边变量x,同时把下一yield语句(y = yield a + x)右边表达式的值(a + x)并赋给g,即x=20,g=10+20(a+x)
- g = j.send(30)传进30,将30赋值给本yield语句(y = yield a+x)的左边变量y,因为无下个yield语句,所以报错,协程中止。
希望下图能帮助你(截自流畅的python)
协程中止
协程中一旦出现未处理的异常,就会立即中止,
def average():
c = 0
t = 0
a = None
while True:
term = yield
if term is None:
break
c += 1
t += term
a = t/c
return c,a
k = average()
next(k)
k.send(123)
k.send(None)
#StopIteration: (1, 123.0)
可以通过指定一个值,在函数内判断来提前中止循环,循环中止后会返回return 表达式的值,但是return表达式的值是偷偷传给调用方,赋值给StopIteration异常的一个属性(value)。可以通过异常处理获取这个值。
yield from
这是一个全新的语言结构,比yield作用更多,在生成器gen中使用yield from subgen()时,subgen会获得控制权,把产出值传给gen调用方,即调用方可以直接控制subgen()。与此同时,gen会阻塞,等待subgen终止。yield from 主要公式是打开双向通道,将最外层调用方与最内层的子生成器连接起来,两者可以直接发送和产出值。
这是yield from 的一简单作用,替代产出值的嵌套for循环。
def chain(*iterable):
for i in iterable:
for j in i:
yield j
chain('abc','123')#['a', 'b', 'c', '1', '2', '3']
def chain1(*iterable):
for i in iterable:
yield from i
chain1('abc','123')#['a', 'b', 'c', '1', '2', '3']
举一个例子,注意下图执行程序所花时间。协程在执行过程中没有等待当前子程序执行完就继续执行下一个子程序。
未完待续……