python 协程

yield from 协程
如果一个生成器内部需要遍历另外一个生成器, 并将数据返给调用者, 你需要遍历并处理所遇到的异常, 而使用yield from 一行就可以处理这样的问题。

调用 yield from gen 时候我们无法判定我遍历了一个生成器还是调用了一个协程。这种混淆使得接口的设计者和使用者者需要花费额外的工作来约定和检查。

于是Python先后添加了 asyncio.coroutine 和types.coroutine这两个装饰器来标识协程, 有这两个装饰就是协程, 这样我们在使用协程的时候不至于误用了生成器。顺带一提,前者是 asyncio 库的实现,需要保持向下兼容,本文暂不讨论;后者则是 Python 3.5 的语言实现,实际上是给函数的 code.co_flags 设置 CO_ITERABLE_COROUTINE 标志。随后,async def 也被引入以用于定义协程,它则是设置 CO_COROUTINE 标志

这样协程和生成器就得到了区分, 其中以types.coroutine定义的协程称为 基于生成器的协程(generator-based coroutine) 而以saync def 定义的协程成为原生协程(native-coroutine)。

这两个协程之间的区别:

原生协程里面不能有yield 或yield from 表达式
原生协程被垃圾回收时候, 如果他还没有被使用过(即 调用await coro 或者await send(NOne)) 会抛出RuntimeWaring
原生协程没有实现 iter和next 方法
简单的生成器(非协程) 不能yield from 原生协程
对原生协程及其函数分别调用inspect.isgenerator() 和inspect.isgeneratorfunction() 将返回false
定义好协程函数之后就可以调用他们了。await 可以用来调用协程, 他的用法和yield from 差不多但是踏只能在协程内部使用, 且只能接awaitable 的对象。 awaitable 对象就是其 await 方法返回一个迭代器的对象。 原生协程和基于生成器的协程都是awaitable的对象。
另外一种调用协程的方法和生成器一样 调用send 方法并自行迭代。这种方式主要是用在非协程函数中调用协程
---------------------
原文:https://blog.csdn.net/yangxiaodong88/article/details/81900985

posted @ 2018-12-31 16:04  Lucas_Yu  阅读(162)  评论(0编辑  收藏  举报