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,一经查实,立即删除!

相关文章

visualsvn php,VisualSVN 手动记录访问日志

VisualSVN 手动记录访问日志VisualSVN 是一个可以免费使用的,SVN服务器端软件,基于 apache 。可以实现 http https 多种SVN 发布功能。VisualSVN 默认是没有日志记录功能,需要手动打开。首先从apache下载,apache 2.2 windows 版&a…

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

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

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

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

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

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

ecshop适应在php7,ecshop适应PHP7的解决方法

if (!defined(DITAN_ECS)){die(Hacking attempt);}class cls_mysql{var $link_id NULL;var $settings array();var $queryCount 0;var $queryTime ;var $queryLog array();var $max_cache_time 300; // 最大的缓存时间,以秒为单位var $cache_data_dir…

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库,支持基于标记和位置的增强现实。开发人员可以…

php基础教学笔记,php学习笔记:基础知识

php学习笔记:基础知识2.每行结尾不允许有多余的空格3.确保文件的命名和调用大小写一致,是由于类Unix系统上面,对大小写是敏感的4.方法名只允许由字母组成,下划线是不允许的,首字母要小写,其后每个单词首字母…

视图编辑php,PhpStorm视图模式

# PhpStorm视图模式在这个页面中:* [基础](#基础)* [切换全屏模式](#切换全屏模式)* [切换演示模式](#切换演示模式)* [切换不分心模式](#切换不分心模式)## 基础PhpStorm提供特定的视图模式:* **全屏模式** 允许你使用整个屏幕编写代码,在视…

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…

asp连oracle测试,ASP连接Oracle

ASP连接Oracle的方式有几种, 这里介绍一下 OLE 连接方法dim objConn,strConn,DBServer,DBName,DBUser,DBPassworddim RS,xSQLDBServer"192.168.1.151" //DB ServerDBName"oracleDB" //登陆数据库名/SIDDBUser"system" //登陆用户名DBPassword&qu…

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…

python创建excel_python自动生成excel(xlwt库)

# coding: utf-8import web import json import datetime import xlwt import StringIO # 如果不在前端调用接口,如下web.py框架的urls和app、render可以省略 urls( # web框架的路由/index,Index,/home,Home, ) appweb.aplication(urls, globals()) # 注册应用 rend…

linux限制单个用户使用,linux下限制用户使用系统资源

linux下限制用户使用系统资源除了可以对用户设置磁盘配额以及权限做限制以外还可以使用ulimit可以对所有用户的core文件大小,数据段大小,最多可使用的CPU事件和最多可打开的文件数目等做限制,将ulimit命令放在/etc/profile文件中,…