详解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中list列表的一些进阶使用方法介绍
Aug 15 Python
python 爬虫出现403禁止访问错误详解
Mar 11 Python
Python创建xml文件示例
Mar 22 Python
Python简单实现Base64编码和解码的方法
Apr 29 Python
基于Django与ajax之间的json传输方法
May 29 Python
python使用tomorrow实现多线程的例子
Jul 20 Python
Python学习笔记之集合的概念和简单使用示例
Aug 22 Python
tensorboard显示空白的解决
Feb 15 Python
keras中的History对象用法
Jun 19 Python
Python文件夹批处理操作代码实例
Jul 21 Python
2021年的Python 时间轴和即将推出的功能详解
Jul 27 Python
Python实现七个基本算法的实例代码
Oct 08 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
超人钢铁侠联手合作?美漫作家呼吁DC漫威合作联动以抵抗疫情
2020/04/09 欧美动漫
php在字符串中查找另一个字符串
2008/11/19 PHP
PHP中改变图片的尺寸大小的代码
2011/07/17 PHP
php导出word文档与excel电子表格的简单示例代码
2014/03/08 PHP
PHP永久登录、记住我功能实现方法和安全做法
2015/04/27 PHP
大家都应该掌握的PHP关联数组使用技巧
2015/12/25 PHP
PHP实现linux命令tail -f
2016/02/22 PHP
PHP针对伪静态的注入总结【附asp与Python相关代码】
2017/08/01 PHP
有关PHP 中 config.m4 的探索
2020/08/26 PHP
JS实现的网页背景闪电闪烁效果代码
2015/10/17 Javascript
原生js实现class的添加和删除简单代码
2016/07/12 Javascript
js实现小窗口拖拽效果
2016/12/03 Javascript
微信小程序开发之录音机 音频播放 动画实例 (真机可用)
2016/12/08 Javascript
Vue 过渡实现轮播图效果
2017/03/27 Javascript
深入浅析Vue全局组件与局部组件的区别
2018/06/15 Javascript
微信小程序上传图片并等比列压缩到指定大小的实例代码
2019/10/24 Javascript
JavaScript利用键盘码控制div移动
2020/03/19 Javascript
在vue中使用防抖函数组件操作
2020/07/26 Javascript
Python实现获取网站PR及百度权重
2015/01/21 Python
python获取远程图片大小和尺寸的方法
2015/03/26 Python
详解Python的Django框架中Manager方法的使用
2015/07/21 Python
Python学习笔记之open()函数打开文件路径报错问题
2018/04/28 Python
解决python读取几千万行的大表内存问题
2018/06/26 Python
完美解决python中ndarray 默认用科学计数法显示的问题
2018/07/14 Python
通过代码实例解析Pytest运行流程
2020/08/20 Python
css3的@media属性实现页面响应式布局示例代码
2014/02/10 HTML / CSS
加拿大高尔夫超市:Golf Town
2018/01/12 全球购物
阿根廷在线宠物商店:Puppis
2018/03/23 全球购物
网上签名寄语活动留言
2014/01/18 职场文书
法律六进活动方案
2014/03/13 职场文书
销售提升方案
2014/06/07 职场文书
施工安全协议书范本
2014/09/26 职场文书
2015年环卫处个人工作总结
2015/07/27 职场文书
详解Javascript实践中的命令模式
2021/05/05 Javascript
【2·13】一图读懂中国无线电发展
2022/02/18 无线电
AudioContext 实现音频可视化(web技术分享)
2022/02/24 Javascript