详解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 相关文章推荐
解决windows下Sublime Text 2 运行 PyQt 不显示的方法分享
Jun 18 Python
Python中getattr函数和hasattr函数作用详解
Jun 14 Python
Python如何获取系统iops示例代码
Sep 06 Python
解决python爬虫中有中文的url问题
May 11 Python
浅谈python之新式类
Aug 12 Python
Python产生一个数值范围内的不重复的随机数的实现方法
Aug 21 Python
python3.7将代码打包成exe程序并添加图标的方法
Oct 11 Python
python中的逆序遍历实例
Dec 25 Python
Python持续监听文件变化代码实例
Jul 22 Python
python/golang 删除链表中的元素
Sep 14 Python
python基础学习之递归函数知识总结
May 26 Python
python中pycryto实现数据加密
Apr 29 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
社区(php&&mysql)一
2006/10/09 PHP
一个简单的PHP投票程序源码
2007/03/11 PHP
PHP 杂谈《重构-改善既有代码的设计》之三 重新组织数据
2012/04/09 PHP
php 模拟post_验证页面的返回状态(实例讲解)
2013/10/28 PHP
php字符串操作常见问题小结
2016/10/11 PHP
关于javascript中的parseInt使用技巧
2009/09/03 Javascript
JavaScript 学习技巧
2010/02/17 Javascript
鼠标划过实现延迟加载并隐藏层的js代码
2013/10/11 Javascript
js计算任意值之间随机数的方法
2015/01/16 Javascript
JS实现简单路由器功能的方法
2015/05/27 Javascript
JS+DIV+CSS排版布局实现美观的选项卡效果
2015/10/10 Javascript
JavaScript实现输入框(密码框)出现提示语
2016/01/12 Javascript
jQuery模拟窗口抖动效果
2017/03/15 Javascript
js实时监控文本框输入字数的实例代码
2018/01/18 Javascript
JavaScript复制内容到剪贴板的两种常用方法
2018/02/27 Javascript
微信小程序实现单列下拉菜单效果
2019/04/25 Javascript
vue实现前台列表数据过滤搜索、分页效果
2019/05/28 Javascript
js原生map实现的方法总结
2020/01/19 Javascript
JS前端模块化原理与实现方法详解
2020/03/17 Javascript
深入解读VUE中的异步渲染的实现
2020/06/19 Javascript
解决vue组件销毁之后计时器继续执行的问题
2020/07/21 Javascript
python通过函数属性实现全局变量的方法
2015/05/16 Python
详解Python中的正斜杠与反斜杠
2019/08/09 Python
Python实现微信翻译机器人的方法
2019/08/13 Python
pytorch 模型可视化的例子
2019/08/17 Python
python线程的几种创建方式详解
2019/08/29 Python
HTML5通过调用canvas对象的getContext()方法来获取绘图环境
2014/06/23 HTML / CSS
美国睫毛、眉毛精华液领导品牌:RevitaLash Cosmetics
2018/03/26 全球购物
印度购买眼镜和太阳镜网站:Coolwinks
2018/09/26 全球购物
新西兰杂志订阅:isubscribe
2019/08/26 全球购物
物业管理计划书
2014/01/10 职场文书
个人对照检查材料
2014/02/12 职场文书
好媳妇事迹材料
2014/12/24 职场文书
小学班主任个人总结
2015/03/03 职场文书
为什么中国式养孩子很累?
2019/08/07 职场文书
浅谈怎么给Python添加类型标注
2021/06/08 Python