python  generator与coroutine

协程

简单介绍

协程,又称微线程,纤程,英文名Coroutine。
协程是一种用户态的轻量级线程,又称微线程。
协程拥有自己的寄存器上下文和栈,调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。

优缺点

优点:
1.无需线程上下文切换的开销
2.无需原子操作锁定及同步的开销
3.方便切换控制流,简化编程模型
4.高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。
所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。
原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序是不可以被打乱,或者切割掉只执行部分。视作整体是原子性的核心。

缺点:
1.无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
但是多进程+协程,可以充分利用多核,又充分发挥协程的高效率,可获得极高的性能。
2.进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序。

协程可以用在哪些场景呢

可以归纳为非阻塞等待的场景,如游戏编程,异步IO,事件驱动。

协程详解

Python对协程的支持是通过generator(生成器)实现的。

要理解生成器,我们先要理解迭代器。什么是迭代器?

在python中一个可以迭代的数据调用iter方法,就可以得到一个迭代器,这个迭代器一定具有next方法,在调用这个迭代器的next方法时,迭代器就回返回它的下一个值,当迭代器中没有值可以返回了,就回抛出一个名为StopIteration的异常,停止迭代。

什么是生成器?

生成器是一个特殊的程序,可以被用作控制循环的迭代行为,python中生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。
 生成器是个比较特殊的可迭代对象,它与其他的可迭代对象不太一样的地方,其他的可迭代对象需要调用iter方法,返回个迭代器对象,然后通过迭代器对象去执行next方法,获取迭代器中的值,但是生成器直接可以被迭代,无需执行iter方法。

至少我们现在要明白

1.带有 yield 的函数不再是一个普通函数,而是一个生成器generator.
2.生成器是可以迭代的,使用next()方法.
3.生成器(generator)能够迭代的关键是它有一个next()方法,工作原理就是通过重复调用next()方法,直到捕获一个异常。

4.协程是通过生成器的实现的
5.协程有四个状态,如下:
•'GEN_CREATED' 等待开始执行。
•'GEN_RUNNING' 解释器正在执行。
•'GEN_SUSPENDED' 在 yield 表达式处暂停。
•'GEN_CLOSED' 执行结束。

第一个示例程序

test为生成器,即可以迭代,我们可以使用next方法迭代。

第11行创建生成器test,在python的函数(function)定义中,只要出现了yield表达式(Yield expression),那么事实上定义的是一个generator function, 调用这个generator function返回值是一个generator。

第12行打印生成器。

第14行我们可以了生成器的状态,结果为:GEN_CREATED。

第15行第一次执行next方法,send和next操作都是调用生成器,而第一调用生成器就是启动生成器,启动生成器必须使用next()语句或是send(None)启动生成器,不能使用send发送一个非None的值,例如send(None),程序运行到yield 1,程序在这里暂停执行,并返回1,我们要明白在这里yield有了return的功能,返回了1,而且还暂停了程序。

第16行我们再次打印生成器的状态,结果:GEN_SUSPENDED。

第17行第二次执行next方法,程序运行到yield 2,程序在这里暂停,并返回2。

现在就很清晰了,使用yield可以切出生成器,它还有return的功能,切进生成器可以使用next()方法。

调用生成器的next(),将运行到yield位置,此时暂停执行环境,并返回这条语句yield关键词后面跟随的值。 这是next()的使用方法。

 1 import inspect
 2 def func1():
 3     yield 1
 4     print("第一个yield执行完成~")
 5     yield 2
 6     print("第二个yield执行完成~")
 7     yield 3
 8     print("第三个yield执行完成~")
 9
10
11 test = func1()
12 print(test)
13
14 print("还未执行next:",inspect.getgeneratorstate(test))
15 next(test)
16 print("第一次执行next:",inspect.getgeneratorstate(test))
17 next(test)
18 print("第二次执行next:",inspect.getgeneratorstate(test))
19 next(test)
20 print("第三次执行next:",inspect.getgeneratorstate(test))
21 next(test)
22 print("第四次执行next:",inspect.getgeneratorstate(test))

运行结果:

<generator object func1 at 0x0000019ABDFABB88>
Traceback (most recent call last):
还未执行next: GEN_CREATED
第一次执行next: GEN_SUSPENDED
第一个yield执行完成~
第二次执行next: GEN_SUSPENDED
第二个yield执行完成~File "C:/Pycham/异步编程/test3.py", line 21, in <module>
第三次执行next: GEN_SUSPENDED
第三个yield执行完成~next(test)
StopIteration

第二个示例程序

在上面的列子我们使用next()切进了生成器,但是每次切换进生成器,都没有传入参数,接下来将介绍send()方法,send()方法不仅可以切进生成器,而且还可以携带参数。

除了next和send方法,generator还提供了两个实用的方法,throw和close,这两个方法加强了caller对generator的控制。send方法可以传递一个值给generator,throw方法在generator挂起的地方抛出异常,close方法让generator正常结束(之后就不能再调用next send了)。

 1 import sys
 2 def func2(a):
 3     print('-> Started: a =', a)
 4     b = yield a
 5     print('-> Received: b =', b)
 6     c = yield a + b
 7     print('-> Received: c =', c)
 8
 9 test = func2(2)
10 value = next(test)# 协程执行到`b = yield a`处暂停,等待为b赋值,并返回a
11 print(value)
12 value = test.send(88)# 协程执行到`c = yield a + b`处暂停,等待为c赋值,并返回a + b
13 print(value)
14 try:
15     test.send(11)
16 except StopIteration:
17     sys.exit(0)

运行结果:

-> Started: a = 2
2
-> Received: b = 88
90
-> Received: c = 11

第三个示例程序

传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高:

 1 import time
 2
 3 def cumtom(name):
 4     print('%s准备吃包子' %name)
 5     time.sleep(1)
 6     while 1:
 7         count=yield
 8         print('%s吃到第%d个包子' %(name,count))
 9
10 def producter():
11     next(con1)
12     next(con2)
13     # con1.__next__()
14     # con2.__next__()
15     n=1
16     while 1:
17         time.sleep(1)
18         print('已经生产出来%d、%d个包子' %(n,n+1))
19         #通过send方法通知
20         con1.send(n)
21         con2.send(n+1)
22         n+=2
23
24 #cumtom函数里面有yield,这里传递参数,会创建一个生成器对象,(提前做了预处理)
25 con1=cumtom('cumtom1')
26 con2=cumtom('cumtom2')
27 producter()

转载于:https://www.cnblogs.com/-wenli/p/11069216.html

python generator与coroutine相关推荐

  1. python generator输出_python 高级特性:Generator(生成器)

    格式对比: List Imprehensions 格式:[ 语句 for .. in ..] Generator 格式:(语句 for .. in ..) 区别:List存储的是具体内容,每个元素都占 ...

  2. C++20 coroutine 探索I:co_await 原理 | 使用 C++ 协程写 python generator

    时隔三个月,才回到当时说的学协程的坑,中间学了各种各样的东西,起码对现代 C++ 有些许了解了.尾递归优化 快速排序优化 CPS 变换 call/cc setjmp/longjmp coroutine ...

  3. c++ 协程_理解Python协程(Coroutine)

    由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...

  4. python generator长度_Python 高级特性之:生成器(generator)和迭代器(Iterator)

    前言: 之前学习Python自动化,接触了不少python的学习,对生成器印象尤其深,网上也看了很多介绍,下面主要是这些概念的个人学习整理(如侵删). 正文: 如要创建一个非常大的列表,受到内存限制, ...

  5. python generator

    1.使用列表占用内存大 def fab(max):L = []n, a, b = 0, 0, 1while n < max:L.append(b)a, b = b, a + bn += 1ret ...

  6. python generator转为list_Python中的 List Comprehension 以及 Generator

    11行代码就写出了一个配置文件的解析器. def loadUserInfo(fileName): userinfo = {} file = open(fileName, "r") ...

  7. Python: generator, yield, yield from 详解

    1.Generator Expressions 生成器表达式是用小括号表示的简单生成器标记法: generator_expression ::= "(" expression co ...

  8. 关于 Python generator(生成器)的类比

    Python 的生成器运用仿佛是最完美的 xing爱,生成器本身和循环代表男女,结束代表同时达到高潮,不是很精准,但很有趣啊!哈哈哈,一下记住了 转载于:https://www.cnblogs.com ...

  9. python generator iterator_Python:Iterator、Generator和Yield总结

    一.Iterator和Iterable 首先,要明白Iterable可迭代对象 和Iterator 迭代器的区别. 类中实现了__iter__(),那就认为它有迭代能力,其对象即可迭代对象,具有迭代能 ...

最新文章

  1. 在 Linux 上用 dust 代替 du更直观
  2. Windows 系统电脑开机速度加快
  3. 【软考-软件设计师】编译程序基本原理
  4. mysql variables 大记录 查询 慢_MySQL - 慢查询
  5. java实现动态验证码源代码——jsp页面
  6. navicat模型显示注释_RetinaNet模型构建面罩检测器
  7. linux开机自动启动开机日志,设置linux开机自动运行脚本
  8. vue脚手架vue数据交互_学习Vue:3分钟的交互式Vue JS教程
  9. java面向对象程序课本,Java面向对象程序设计
  10. Q96:PT(1):方格纹理(Checker)(2)——2D Checker
  11. 谁提供一个能用的ICHAT文字聊天室程序,急需
  12. 拍照识别身份证 Android/iOS身份证识别技术
  13. apue.3e环境配置
  14. C语言从入门到入土---初识C语言
  15. Python小白的飞桨之旅
  16. U-boot简介及常用命令说明
  17. 诺布酒店在希腊的第一家酒店餐厅圣托里尼诺布酒店餐厅今年春季开业;爱彼迎邀旅居体验者住进西西里乡村慢生活 | 全球旅报...
  18. 微星主板从u盘启动linux挖矿,三星905s3g BIOS 设置U盘启动
  19. iphone一键转移_苹果手机如何一键转移数据 转移教程介绍
  20. mat-icon 翻转_案例研究-翻转网站以获取利润

热门文章

  1. [转载] 【numpy】numpy.ones()函数
  2. [转载] python怎么将十进制转换为二进制_python十进制和二进制的转换方法(含浮点数)
  3. HTML-JS-CSS基础
  4. 在RedHat下安装MPlayer
  5. WindowsAPI概览
  6. Application应用框架思考(三) 之[插件机制]
  7. C+++之insert()
  8. C++之---友元函数
  9. 数据结构上机实践第八周项目3-顺序串算法
  10. kafka学习_kafka学习(第一章 初识kafka)