详解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中使用urllib2获取http请求状态码的代码例子
Jul 07 Python
Python如何实现文本转语音
Aug 08 Python
分享Python开发中要注意的十个小贴士
Aug 30 Python
python与php实现分割文件代码
Mar 06 Python
对python中return和print的一些理解
Aug 18 Python
python机器学习实战之最近邻kNN分类器
Dec 20 Python
Python基于列表模拟堆栈和队列功能示例
Jan 05 Python
在python3.5中使用OpenCV的实例讲解
Apr 02 Python
pycharm 将django中多个app放到同个文件夹apps的处理方法
May 30 Python
简单了解django缓存方式及配置
Jul 19 Python
Python爬虫爬取博客实现可视化过程解析
Jun 29 Python
python三子棋游戏
May 04 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
提问的智慧(2)
2006/10/09 PHP
PHP基础知识回顾
2012/08/16 PHP
Laravel 6 将新增为指定队列任务设置中间件的功能
2019/08/06 PHP
jQuery 开天辟地入门篇一
2009/12/09 Javascript
JavaScript 错误处理与调试经验总结
2010/08/10 Javascript
JS Replace()的高级使用方法介绍
2013/06/29 Javascript
jQuery对下拉框,单选框,多选框的操作
2014/02/21 Javascript
js数组与字符串的相互转换方法
2014/07/09 Javascript
基于jquery的文字向上跑动类似跑马灯的效果
2014/09/22 Javascript
jquery中trigger()无法触发hover事件的解决方法
2015/05/07 Javascript
Bootstrap实现圆角、圆形头像和响应式图片
2016/12/14 Javascript
JavaScript满天星导航栏实现方法
2018/03/08 Javascript
AngularJS发送异步Get/Post请求方法
2018/08/13 Javascript
Node.js 的 GC 机制详解
2019/06/03 Javascript
解决layui checkbox 提交多个值的问题
2019/09/02 Javascript
9种方法优化jQuery代码详解
2020/02/04 jQuery
JQuery事件冒泡和默认行为代码实例
2020/05/13 jQuery
js编写简易的计算器
2020/07/29 Javascript
vue 实现element-ui中的加载中状态
2020/11/11 Javascript
介绍Python中的fabs()方法的使用
2015/05/14 Python
python下paramiko模块实现ssh连接登录Linux服务器
2015/06/03 Python
python3实现磁盘空间监控
2018/06/21 Python
django drf框架中的user验证以及JWT拓展的介绍
2019/08/12 Python
Python函数参数类型及排序原理总结
2019/12/19 Python
python3实现往mysql中插入datetime类型的数据
2020/03/02 Python
python 双循环遍历list 变量判断代码
2020/05/04 Python
Python调用C/C++的方法解析
2020/08/05 Python
Python下载网易云歌单歌曲的示例代码
2020/08/12 Python
html5 touch事件实现触屏页面上下滑动(二)
2016/03/10 HTML / CSS
StubHub新加坡:购买和出售全球活动门票
2017/03/10 全球购物
法国隐形眼镜网站:VisionDirect.fr
2020/03/03 全球购物
本科应届生自荐信
2014/06/29 职场文书
企业安全生产目标责任书
2014/07/23 职场文书
三好学生评语大全
2014/12/29 职场文书
JavaScript实现简单图片切换
2021/04/29 Javascript
python文件目录操作之os模块
2021/05/08 Python