问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

协程系列(2) Python 的生成器和协程语法

发布网友 发布时间:2024-09-09 14:03

我来回答

1个回答

热心网友 时间:2024-10-10 23:13

希望你已经阅读了上一篇文章,知道了什么是协程。在这篇文章中,我们将介绍Python的协程语法。

上期我们提到,一个可以暂停并且恢复的函数,就是一个协程。Python从3.5开始,通过PEP 492引入了新的语法,用于定义协程。这个语法是async def和await。但在之前,我想先介绍Python的生成器语法,因为生成器和协程有很多相似之处。

在函数中定义一个yield语句,就可以将一个函数变成生成器。

生成器是一种特殊的迭代器,它可以暂停并且恢复。生成器的定义和普通函数类似,只是在函数体中使用yield语句。

我们来看一个简单的例子:

g是一个生成器对象,它是通过调用simple_generator函数得到的。

生成器执行到yield语句时,会暂停,并且返回yield后面的值。

生成器对象有send方法,用于恢复生成器执行,这个参数会成为生成器中yield语句的返回值。

所以,第一次调用g.send(None),生成器恢复运行,直到第一个yield语句,返回123,被存入y中。

这时候继续调用g.send(1),生成器会继续执行。send的参数1会被存入x中。

生成器继续运行,直到第二个yield语句,返回456,存入y中。

再次调用g.send(2),生成器会继续执行,2被存入x中,运行到函数体结束。在最后,生成器会抛出StopIteration异常,表示生成器执行结束。

程序输出如下:

StopIteration异常被捕获,表示生成器执行结束。StopIteration异常的value属性,就是生成器的返回值。

PEP 492引入了async def和await语法,用于定义协程。它与生成器有很多相似之处。

await语句,它会暂停当前协程,并且等待coro协程执行结束。c是一个协程对象,它是通过调用simple_coro函数得到的。

协程对象有send方法,用于恢复协程执行,这个参数会成为await语句的返回值。

通过types.coroutine装饰器,可以将一个生成器函数变成一个协程函数。

第一步,调用c.send(None),协程恢复运行,直到await语句,等待coro1协程执行结束。

这时候进入coro协程,执行到yield语句,暂停,返回12345。这个值被存入y中。

程序输出为:

第二步,调用c.send(1),协程恢复运行,1被存入x1中,运行到函数体结束。在最后,协程会抛出StopIteration(123)异常,表示协程执行结束。

这时候StopIteration异常被捕获,123被存入x2中。

程序继续执行到return 456,然后抛出StopIteration(456)异常,表示协程执行结束。

这时候StopIteration异常被捕获,456被存入y中。

程序输出为:

在CPython实现中,生成器和协程是不同的东西,但是他们的实现非常相似。可以在CPython源代码中搜索PyGenObject是生成器的结构体,PyCoroObject是协程的结构体。

这两个对象的内部都持有完整的程序栈帧,也会记录字节码运行到哪一条,以及一些额外的状态信息。因为CPython实现中,要保存局部状态,必须保存完整的程序栈帧,由于其动态性,是无法预先知道需要哪些保存局部变量的。

所以话说回来,有栈协程和无栈协程在Python里更多还是靠语法和切换状态来区分。

CPython把await编译到相对应的字节码指令,遇到的时候就直接切进那个栈帧,然后执行那个栈帧,然后返回结果。这个过程和生成器的yield语句很像。

生成器和协程都是可以暂停并且恢复的函数。生成器通过yield语句实现,协程通过await语句实现。通过send方法,可以恢复生成器和协程的执行。

此外,生成器和协程还有throw和close方法,我略去了。有兴趣的可以在下面的链接中查看详细说明。

asyncio正如我们上一篇文章中所说的,是Python的协程库。它提供了一些高级的API,用于管理协程的执行。通过asyncio,可以很方便的编写异步程序。但没有asyncio,照样可以使用生成器和协程,编写异步程序。

在下一篇文章中,我们将介绍asyncio的关键组件,Future和Task。

Task和Future是asyncio的核心,也是asyncio的最小调度单元。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
...的电器到成都,请问一下,那个航空快一些呀,多少/公斤? 前女友和我分手一年之后,出车祸死了,我很高兴,这种心理是不是不... 为什么听到前女友去世的消息,我竟然放声大哭,她很爱我,是我对她腻了... 兰州银行充天然气必须要本行卡吗 从服饰礼仪看中西方文化差异 为什么iqoo11评价那么低? 相机快门线的运用范围 快门线是干什么用的 请问这是什么虫子 还挺硬的 在楼房内 整理箱上面发现的 屋内有木质上... 请问这是什么虫子?家里抓到,2cm左右。坐标北京,昌平,冬季12月,楼房... 推荐几个代码自动生成器,神器!!! django怎么生成随机验证码? 1立方分米的锂比1立方分米的氧气轻吗? 解锁Python生成器:双向通信和send()方法 一、填空。 1、9.87升=( )升( )毫升, 2700立方厘米=( )立方分米 2、用... 用同样材质的铜制成两个零件一个体积是十五立方厘米重一百三十三点五... yandex广告投放 想和前任复合是对的吗? 分手很久后再复合,还有爱情吗? 新鲜玉米怎么保鲜好吃新鲜玉米怎么储存能保持新鲜 怎样储存才能让玉米不断保持鲜美的口感? 我是学生,我想买一个U盘,主要存储日常常用文件和做成PE启动盘。请问一... 梦到自己额头上都是黑头 挤出来很大坨的东西 很恶心 这是怎么回事_百度... 2024年U盘选购攻略,全人群U盘推荐(学生党/职场人/设计等) u盘多大合适,学生用。 Word文档中字体分散怎么设置 Word文档如何设置两端对齐、分散对齐 岁月是多双生花,结局好不好 word表格如何使文字分散对齐? 为什么word文档里的文字自动分散对齐? JeecgBoot 2.4 微服务正式版发布,基于SpringBoot的低代码平台 我爱薅羊毛红包版 为什么恒星温度越高颜色就越蓝 高温蓝色预警信号重要意义 什么是高温蓝色预警 syd表示什么 三明教育局电话 三明市教育局体卫艺科电话 为什么三明市教育局的地理位置设置在三明市新市北路25栋沪明新_百度... 丈夫犯诈骗罪,妻子一方要承担责任吗 不见你又想见你,见到你又叹气什么意思 诈骗退赃会涉及到夫妻财产吗 夏天的天空为什么那么蓝夏天的天空为何那么蓝 妇科体检后 入厕后擦拭有淡血色已经5天了是怎么回事 惜指失掌是什么生肖动物 后背上先开始摸着有两小块很干的皮 然后一直没太在意 现在成片了 越来... 后背皮肤摸起来像粗糙怎么办 大华硬盘录像机忘记密码怎么解决呢 如何拆锁舌 聘用合同与劳动合同不同点是什么