c++ 协程_用yield实现协程

9aeb6027a9e1bddc5d71848cf493bef5.png

上一篇 理解python中的yield关键字 介绍了使用yeld实现生成器函数,这一篇我们来继续深入的了解一下yield,用yield实现协程。

先来解答一下上一篇留下的问题:下面的代码为什么第二次调用next打印None呢?

def 

事实是这样的,yield语句默认返回None。当第一次调用next方法时,生成器函数开始执行,执行到yield表达式为止,但此时赋值操作并为执行。上面的代码中,在第一次调用next的时候,echo生成了1。第二次调用next的时候,yield表达式的值赋给了n,n此时变成None了,再次yield n的时候就自然生成None了。

好了,接下来开始本文的主题。

什么是协程

引用官方的说法:

协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

与线程相比,协程更轻量。一个Python线程大概占用8M内存,而一个协程只占用1KB不到内存。协程更适用于IO密集型的应用。

在讲述协程的实现前,我们有必要先来看一下send方法。

send方法

yield表达式有一个返回值,send方法的作用就是控制这个返回值,send的参数就是yield表达式的返回值。我们来看一下官方文档上关于send的定义

generate.send(value):
生成器的send(value)方法会将value值“发送”给生成器中的方法。value参数变成当前yield表达式的值。send()方法会返回生成器生成的下一个yield值或者StopIteration异常(如果生成器没有生成下一个yield值就退出了)。当通过调用send()启动生成器时,value值必须为None,因为当前还没有yield表达式可以接收参数。

是不是看晕了?我们来看一个例子

def 

上面的代码输出

before yield
after yield: 1
before yield
after yield: 2
before yield
after yield: None
before yield

第一次调用next的时候,程序从函数最开始处运行,打印出

before yield

执行到yield处,停在该处。

接下来,向生成器send(1)。send在这里起到两个作用,一个是将参数值赋给yield的返回值,然后该返回值赋给了变量x;一个是继续程序的执行,直到下一次遇到yield停下来。第二个功能和next类似。其实,next 就相当于 send(None) 。

执行了 send(1) 后,x被赋值给yield的返回值,即send的参数1,并继续往下执行,打印出了

after yield: 1

继续执行,回到循环的开始,向下执行,打印出

before yield

再次遇到yield,停在该处,等待下一次send或next的调用。

向生成器send(2)。这里的步骤和 send(1) 相同,打印出下面两条后,在yield处停住。

after yield: 2

before yield

执行 next(g),x被赋值为yield表达式的返回值,也就是None,继续向下执行,打印出

after yield: None

再次回到循环的开始,向下执行,打印出

before yield

程序运行结束。

现在是不是有点理解send了?

yield和send实现Python协程

我们来用协程实现一个生产者/消费者的例子

import 

运行上面的程序,会输出

[producer] producing 1...
[consumer] consuming 1...
[producer] consumer return: well received
[producer] producing 2...
[consumer] consuming 2...
[producer] consumer return: well received
[producer] producing 3...
[consumer] consuming 3...
[producer] consumer return: well received
[producer] producing 4...
[consumer] consuming 4...
[producer] consumer return: well received
[producer] producing 5...
[consumer] consuming 5...
[producer] consumer return: well received

produce函数负责生产数据,consume函数负责消费数据。具体执行过程如下:

  1. 首先调用consume函数,consume函数的返回是一个生成器,把这个生成器传入produce函数。
  2. produce函数中调用next(c)启动生成器。
  3. 计算 n = n+1 生成数据,一旦生产了数据,调用 c.send(n) 切换到consume执行。
  4. consume函数中拿到数据后赋值给n,继续执行yield后面的语句。
  5. consume函数中打印消费的数据,并设置返回值r,又回到循环的开始,通过yield把结果传回。
  6. produce拿到consume返回的值,继续生产下一个数据。
  7. 5个数据生产完毕后,循环结束,通过c.close()关闭consume,结束全过程。

produce和consume函数在一个线程内执行,通过调用send方法和yield互相切换,实现协程的功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/506358.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pandas 第一行_用Excel表格带你学习pandas最核心的处理操作,不再害怕条件统计

此系列文章收录在公众号中:数据大宇宙 > 数据处理 >E-pd转发本文并私信我"python",即可获得Python资料以及更多系列文章(持续更新的)经常听别人说 Python 在数据领域有多厉害,结果学了很长时间,连数据处理都麻烦得…

网页载入动画 php,网站页面加载动画代码

有时候网站服务器带宽不好或者用户网络不好,网站速度打开就会比较慢,那么用户等待就会比较无聊,下面准备了一个loading页面,可以在网站文件未完全加载完毕之前展示。HTML部分,放在body标签下面(最好是最靠近body)正在加…

ehcache缓存原理_贼厉害,手撸的 SpringBoot缓存系统,性能杠杠的!

缓存是最直接有效提升系统性能的手段之一。个人认为用好用对缓存是优秀程序员的必备基本素质。本文结合实际开发经验,从简单概念原理和代码入手,一步一步搭建一个简单的二级缓存系统。一、通用缓存接口1、缓存基础算法FIFO(First In First Ou…

angular 字符串转换成数字_Angular日期在TypeScript中格式化转换应用

组件模板中我们常常使用Angular内置管道DatePipe将其日期格式化,如同{{ startTime | date:yyyy-MM-dd }}这般操作,即可转换为字符串格式。那么在TS文件中我们也可以通过DatePipe或formatDate方法将其格式化。Angular日期在TypeScript中格式化转换应用​w…

python罗马数字转换,Python3.5实现的罗马数字转换成整数功能示例

本文实例讲述了Python3.5实现的罗马数字转换成整数功能。分享给大家供大家参考,具体如下:问题概述:给定一个罗马数字 ,将罗马数字转换成整数。如罗马数字I,II,III,IV,V分别代表数字 …

js在一个指定元素前添加内容_WebAR开发指南(1)---使用AR.js实现第一个WebAR demo...

前面有一篇文章万字干货介绍WebAR的实现与应用 分析了目前流行的WebAR框架并简单的介绍一些实现方法,这个专栏我们具体的来通过一些框架实现WebAR效果。关于AR.jsAR.js是一个轻量级的增强现实类JavaScript库,支持基于标记和位置的增强现实。开发人员可以…

python 最小二乘回归 高斯核_从简单数学建模开始:08最小二乘准则的应用(附python代码)...

模型拟合一般来说有这么三种:切比雪夫近似准则极小化绝对偏差之和最小二乘准则这几个原则各有各的适用范围。其中最小二乘准则是比较容易计算的。接下来我将简要的介绍最小二乘准则以及举例说明如何用python实现。最小二乘准则定义:给定某种函数类型 和 …

oracle 时间集合,oracle 日期函数集合(集中版本)第2/2页

oracle 日期函数集合(集中版本)第2/2页更新时间:2009年06月16日 23:45:55 作者:oracle 日期函数网上已经有了不少,特我们跟集中一下,免得大家麻烦。一、 常用日期数据格式1.Y或YY或YYY 年的最后一位,两位或三位SQL&g…

中缀表达式转后缀表达式两位数_再见,正则表达式!

从一段指定的字符串中,取得期望的数据,正常人都会想到正则表达式吧?写过正则表达式的人都知道,正则表达式入门不难,写起来也容易。但是正则表达式几乎没有可读性可言,维护起来,真的会让人抓狂&a…

php 腾讯云 文字识别_腾讯科技(成都)有限公司

成都IT内推圈是由IT行业老兵组建的民间组织,我们希望能为广大IT同仁提供力所能及的帮助,我们不仅提供靠谱的职位,我们更是有温度的圈子!为了帮助更多的朋友寻找到靠谱的内推职位,老农在此号召大家:1. 发布职…

oracle插入性能优化,Oracle- insert性能优化

看见朋友导入数据,花了很长时间都没完成!其实有很多快速的方法,整理下!向表中插入数据有很多办法,但是方法不同,性能差别很大.----1.原始语句drop table t1 purge;create table t1(sid number,sname varchar2(20)) tab…

winscp 自动断开无法连接_winscp教程,winscp教程,看完就学会的winscp教程

作为一个站长,当你的网站流量逐渐变大时,就会发现目前的主机无法满足正常需要,就要更换更高一级的云主机或VPS主机,新手就需要使用WinSCP和Putty,来管理主机。IIS7服务器管理工具可以批量管理、定时上传下载、同步操作…

oracle客户端数据恢复,AnyBackup-Oracle 数据恢复任务恢复到异客户端失败,并提示错误:数据源为空,请检查恢复环境是否授权...

关键字Oracle、数据源适用产品AnyBackup Express 7.0.6 - 7.0.8AnyBackup CDM 7.0.6 - 7.0.8问题描述登录 AnyBackup 管理控制台,依次点击定时数据保护 > 数据恢复 > 新建,新建 Oracle 数据恢复任务,选择恢复数据到异客户端&#xff0c…

linux祖先进程,Linux下的几种特殊进程

1、Linux的登录环境Linux是一个多任务多用户的操作系统,其设计初衷: 就是要达成多用户同时使用单个计算机大的任务。多用户:早期计算机资源紧张,为了让更多的人都可以使用。多任务:服务于多用户,同时提高计算机的吞吐量…

@select注解_SSM框架(十三):Spring框架中的IoC(3)新注解,完全摆脱xml文件

spring中的新注解1、Configuration作用:指定当前类是一个配置类细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。2、ComponentScan作用:用于通过注解指定spring在创建容器时要扫描的包属性…

element ui 多个子组件_ElementUI 技术揭秘(2) 组件库的整体设计

需求分析当我们去实现一个组件库的时候,并不会一上来就撸码,而是把它当做产品一样,思考一下我们的组件库的需求。那么对于 element-ui,除了基于 Vue.js 技术栈开发组件,它还有哪些方面的需求呢。丰富的 feature&#x…

arraylist线程安全吗_Java的线程安全、单例模式、JVM内存结构等知识梳理

java技术总结知其然,不知其所以然 !在技术的海洋里,遨游!做一个积极的人编码、改bug、提升自己我有一个乐园,面向编程,春暖花开!本篇以一些问题开头,请先不看答案,自己思…

【GitHub精选项目】抖音/ TikTok 视频下载:TikTokDownloader 操作指南

前言 本文为大家带来的是 JoeanAmier 开发的 TikTokDownloader 项目,这是一个高效的下载 抖音/ TikTok 视频的开源工具。特别适合用户们保存他们喜欢的视频或分享给其他人。 TikTokDownloader 是一个专门设计用于下载 TikTok 视频的工具,旨在为用户提供一…

python的界面文字翻译_一个把网站全英文转成中文的方法,让你轻松看懂python官网...

近日,在看python官网(英文网站)时,使用了有道翻译工具查看了几个专有名词。无意间,有了是不是可以输入网站地址进行翻译的想法,翻译后的网站地址点击进去后,又是一个什么情况呢?小编…

drools规则引擎技术指南_物联网规则引擎技术

物联网应用程序设计与典型的IT解决方案大不相同,因为它将物理操作技术(OT)与传感器、致动器和通信设备连接起来,并将数字信息技术(IT)与数据、分析和工作流连接起来。在企业环境中,物联网非常复…