详解Python生成器和基于生成器的协程


Posted in Python onJune 03, 2021

一、什么是生成器

Generator

1.生成器就是可以生成值的函数
2.当一个函数里有了 yield关键字就成了生成器
3.生成器可以挂起执行并且保持当前执行的状态

代码示例:

def simple_gen():
	yield 'hello'
	yield 'world'

gen = simple_gen()
print(type(gen))  # 'generator' object
print(next(gen))  # 'hello'
print(next(gen))  # 'world'

二、基于生成器的协程

Python3之前没有原生协程,只有基于生成器的协程

1.pep 342(Coroutines via Enhanced Generators)增强生成器功能
2.生成器可能通过 yield 暂停执行和产出数据
3.同时支持send()向生成器发送数据和throw()向生成器抛出异常

Generator Based Corouteine代码示例:

def coro():
	hello = yield 'hello'  # yield 关键字在 = 右边作为表达式,可以被 send 值
	yield hello

c = coro()
# 输出 'hello', 这里调用 next 产出第一个值 'hello',之后函数暂停
print(next(c))
# 再次调用  send 发送值,此时 hello 变量赋值为 'world',然后 yield 产出 hello 变量的值 'world'
print(c.send('world'))
# 之后协程结束,后续再 send 值会抛出异常 StopIteration

运行结果:

详解Python生成器和基于生成器的协程

三、协程的注意点

协程注意点

1.协程需要使用send(None)或者next(coroutine)来预激(prime)才能启动
2.在yield处协程会暂停执行
3.单独的yield value会产出值给调用方
4.可以通过 coroutine.send(value)来给协程发送值,发送的值会赋值给 yield表达式左边的变量value = yield
5.协程执行完成后(没有遇到下一个yield语句)会抛出StopIteration异常

四、协程装饰器

避免每次都要用 send 预激它

from functools import wraps

def coroutine(func):  # 这样就不用每次都用 send(None) 启动了
	“”“装饰器:向前执行到一个 `yield` 表达式,预激 `func` ”“”
	@wrops(func)
	def primer(*args, **kwargs):   # 1
		gen = func(*args, **kwargs)  # 2
		next(gen)  # 3
		return gen  # 4
	return primer

五、python3原生协程

python3.5引入 async/await支持原生协程(native coroutine)

import asyncio
import datetime
import random

async def display_date(num, loop):
	end_time = loop.time() + 50.0
	while True:
		print('Loop: {} Time: {}'.format(num, datetime.datetime.now())
		if (loop.time() + 1.0) >= end_time:
			break
		await asyncio.sleep(random.randint(0, 5))

loop = asyncio.get_event_loop()
asyncio.ensure_future(display_date(1, loop))
asyncio.ensure_future(display_date(2, loop))
loop.run_forever()

 

到此这篇关于详解Python生成器和基于生成器的协程的文章就介绍到这了,更多相关Python生成器与协程内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python计算最大优先级队列实例
Dec 18 Python
Cpy和Python的效率对比
Mar 20 Python
在Python中使用pngquant压缩png图片的教程
Apr 09 Python
Python入门教程之if语句的用法
May 14 Python
Python及Django框架生成二维码的方法分析
Jan 31 Python
Python子类继承父类构造函数详解
Feb 19 Python
python实现二维数组的对角线遍历
Mar 02 Python
Python 保持登录状态进行接口测试的方法示例
Aug 06 Python
解决Python使用列表副本的问题
Dec 19 Python
python异常处理和日志处理方式
Dec 24 Python
如何使用Python破解ZIP或RAR压缩文件密码
Jan 09 Python
基于pytorch中的Sequential用法说明
Jun 24 Python
实例讲解Python中sys.argv[]的用法
Jun 03 #Python
Django与数据库交互的实现
Jun 03 #Python
Python代码风格与编程习惯重要吗?
Jun 03 #Python
python 经纬度求两点距离、三点面积操作
Jun 03 #Python
如何使用PyCharm及常用配置详解
python for循环赋值问题
Jun 03 #Python
python批量创建变量并赋值操作
Jun 03 #Python
You might like
jQuery Mobile + PHP实现文件上传
2014/12/12 PHP
PHP实现根据数组某个键值大小进行排序的方法
2018/03/13 PHP
页面加载完毕后滚动条自动滚动一定位置
2014/02/20 Javascript
Jquery 垂直多级手风琴菜单附源码下载
2015/11/17 Javascript
js实现有过渡渐变效果的图片轮播相册(兼容IE,ff)
2016/01/19 Javascript
极易被忽视的javascript面试题七问七答
2016/02/15 Javascript
vue学习笔记之指令v-text && v-html && v-bind详解
2017/05/12 Javascript
浅析node Async异步处理模块用例分析及常用方法介绍
2017/11/17 Javascript
nodejs+mongodb aggregate级联查询操作示例
2018/03/17 NodeJs
基于iScroll实现内容滚动效果
2018/03/21 Javascript
vuejs 制作背景淡入淡出切换动画的实例
2018/09/01 Javascript
原生JS实现前端本地文件上传
2018/09/08 Javascript
vue.js中proxyTable 转发请求的实现方法
2018/09/20 Javascript
ndm:NPM的桌面GUI应用程序
2018/10/15 Javascript
微信小程序rich-text富文本用法实例分析
2019/05/20 Javascript
微信小程序登录态和检验注册过没的app.js写法
2019/05/22 Javascript
node将geojson转shp返回给前端的实现方法
2019/05/29 Javascript
详解新手使用vue-router传参时注意事项
2019/06/06 Javascript
vue 组件简介
2020/07/31 Javascript
python网络编程学习笔记(五):socket的一些补充
2014/06/09 Python
gearman的安装启动及python API使用实例
2014/07/08 Python
用python找出那些被“标记”的照片
2017/04/20 Python
python实现稀疏矩阵示例代码
2017/06/09 Python
Python实现个人微信号自动监控告警的示例
2019/07/03 Python
pandas读取CSV文件时查看修改各列的数据类型格式
2019/07/07 Python
python实现的汉诺塔算法示例
2019/10/23 Python
新建文件时Pycharm中自动设置头部模板信息的方法
2020/04/17 Python
HTML5进阶段内联标签汇总(小篇)
2016/07/13 HTML / CSS
UGG雪地靴荷兰官网:UGG荷兰
2016/09/09 全球购物
有机婴儿毛毯和衣服:Monica + Andy
2020/03/01 全球购物
现场活动策划方案
2014/08/22 职场文书
2014年社区卫生工作总结
2014/12/18 职场文书
三孔导游词
2015/02/05 职场文书
幼儿园父亲节活动总结
2015/02/12 职场文书
《老人与海鸥》教学反思
2016/02/16 职场文书
基于Redis zSet实现滑动窗口对短信进行防刷限流的问题
2022/02/12 Redis