天天看点

python 协程可以嵌套协程吗_关于Python协程(Coroutine)的理解

从语法上来看,协程和生成器类似,都是在定义体中包含yield关键字的函数

但在

协程中

yield关键字通常出现在表达式的右边:

  1. 可以产出值n(y = yield n)
  2. 也可以不产出值(y = yield),或者说是产出值为None

通过

next(coroutine)

函数

激活协程:
  1. 调用next(),返回 yield右边的可有可无的值或者函数值( 一般不需要next产出值,即, yield后无值,= yield ), 暂停
调用方

是通过

send(datum=None)

的方式把数据提供给协程使用:

  1. send(n)函数的返回值为 yield右边的值或者函数值
  2. 等号左边的变量接受send(n)函数传来的值
  • 可以理解为 函数next()和函数send(n)都 会执行yield右边的 值或者函数值,
  • 但是 send(n)函数执行完 不会暂停 ,同时send(n)函数的 参数n会赋值给等号左边的变量
def 
           
python 协程可以嵌套协程吗_关于Python协程(Coroutine)的理解

这里的对应于

send(n)

的操作 y

= yield

实际上是

按2步进行的
  1. 第1步yield 接受send(n)函数传来的参数值 并赋值 等号=左边 的变量,即y=n
  2. 第2步执行 yield后面的表达式或者函数并返回值

为了查看协程在运行过程中的四个状态,我们引入

from inspect import getgeneratorstate
  1. GEN_CREATED :生成器创建完成,等待执行,可以理解为线程的就绪状态
  2. GEN_RUNNING :一般看不到,可理解为线程的执行状态
  3. GEN_SUSPENDED :在yield表达式处暂停,可理解为线程的阻塞状态
  4. GEN_CLOSED :执行结束,可理解为线程的死亡状态
python 协程可以嵌套协程吗_关于Python协程(Coroutine)的理解

获取协程的返回值

  1. 从异常属性中获取:协程结束时会跟生成器一样抛出StopIteration的异常, 返回值 就在异常对象的 value 属性中
  • yield from内部会自动捕获 后面 协程StopIteration异常,并把异常对象的value属性变成yield from的返回值
  • yield from 的主要功能就是打开双向通道,最外层的调用方调用 子生成器 ,同时子生成器也可使用yield from调用另一个子生成器,一直嵌套调用 直到遇到yield 表达式结束
  • send(n) 发送的值n通过yield from直接传递给了 最内层的子生成器 ,并在yield from处等待子生成器的返回
python 协程可以嵌套协程吗_关于Python协程(Coroutine)的理解

丛异常中获取协程返回值(1)

python 协程可以嵌套协程吗_关于Python协程(Coroutine)的理解

丛异常中获取协程返回值(2)

异步IO(asyncio)

  • Python 3.4版本引入 异步IO的标准库asyncio, 使用事件循环 驱动协程 实现并发。
  • 在asyncio库中, 用asyncio.coroutine装饰 用yield from来驱动协程
  • Python 3.5版本中 用async代替了 asyncio.coroutine,用 await代替了 yield from

下面展示了Python 3.4中标准库

asyncio

中协程(coroutine)的应用

import threading import

asyncio

@asyncio.coroutine

def hello

():

print('Hello world! (%s)' % threading.currentThread())

yield from

asyncio.sleep(1)

print('Hello again! (%s)' % threading.currentThread())

loop = asyncio.get_event_loop()

tasks = [hello(), hello()]

loop.run_until_complete(asyncio.wait(tasks))

loop.close()

asyncio​www.liaoxuefeng.com

python 协程可以嵌套协程吗_关于Python协程(Coroutine)的理解