python技术专栏

python协程

2019-08-12  本文已影响0人  huxt

1.协程前奏概念

并发:操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。

并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。

并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。

同步:调用IO时,等待IO返回才能操作

异步:调用IO时,不必等待IO返回,直接进行下一步

阻塞: 阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回

非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回

2.协程概念

#传统函数调用 过程 A->B->C

协程:#我们需要一个可以暂停的函数,并且可以在适当的时候恢复该函数的继续执行

#出现了协程 -> 有多个入口的函数,可以暂停的函数,可以暂停的函数(可以向暂停的地方传入值)

协程 自定义异常 yield yeild和yield from

yield from

我们有一个嵌套型的序列,想将它扁平化处理为一列单独的值。

代码 运行结果

collections.Iterable是一个抽象基类,我们用isinstance(x, Iterable)检查某个元素是否是可迭代的.如果是的话,那么就用yield from将这个可迭代对象作为一种子例程进行递归。最终返回结果就是一个没有嵌套的单值序列了。

代码中额外的参数ignore types和检测语句isinstance(x, ignore types)用来将字符

串和字节排除在可迭代对象外,防止将它们再展开成单个的字符。

如果这里不用yield from的话,那么就需要另外一个for来嵌套,并不是一种优雅的操作

yield from 的主要功能是打开双向通道,把最外层的调用方与最内层的子生成器连接起来,这样二者可以直接发送和产出值,还可以直接传入异常,而不用在位于中间的协程中添加大量处理异常的样板代码。有了这个结构,协程可以通过以前不可能的方式委托职责



生成器



协程



yield from


生成器消费者和生产者

生产者和消费者

yield from的使用

yield from 


异常捕捉的是return语句



yield from 实例

统计方法


main函数

yield from 可以获取子生成器的retunrn的值


运行结果

看完代码,我们总结一下关键点:

1. 子生成器生产的值,都是直接传给调用方的;调用方通过.send()发送的值都是直接传递给子生成器的;如果发送的是 None,会调用子生成器的__next__()方法,如果不是 None,会调用子生成器的.send()方法;

2. 子生成器退出的时候,最后的return EXPR,会触发一个StopIteration(EXPR)异常;

3. yield from表达式的值,是子生成器终止时,传递给StopIteration异常的第一个参数;

4. 如果调用的时候出现StopIteration异常,委托生成器会恢复运行,同时其他的异常会向上 "冒泡";

5. 传入委托生成器的异常里,除了GeneratorExit之外,其他的所有异常全部传递给子生成器的.throw()方法;如果调用.throw()的时候出现了StopIteration异常,那么就恢复委托生成器的运行,其他的异常全部向上 "冒泡";

6. 如果在委托生成器上调用.close()或传入GeneratorExit异常,会调用子生成器的.close()方法,没有的话就不调用。如果在调用.close()的时候抛出了异常,那么就向上 "冒泡",否则的话委托生成器会抛出GeneratorExit异常。


3.原生协程  async/wait

# 生成器是可以暂停的函数

# 第一返回值给调用方, 第二调用方通过send方式返回值给gen

# 用同步的方式编写异步的代码, 在适当的时候暂停函数并在适当的时候启动函数

上一篇下一篇

猜你喜欢

热点阅读