详解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当中的数据类型和变量
Apr 25 Python
Python多进程分块读取超大文件的方法
Apr 13 Python
selenium python浏览器多窗口处理代码示例
Jan 15 Python
python验证码识别教程之利用滴水算法分割图片
Jun 05 Python
python 使用装饰器并记录log的示例代码
Jul 12 Python
Django配置文件代码说明
Dec 04 Python
Python实现井字棋小游戏
Mar 09 Python
Python多线程Threading、子线程与守护线程实例详解
Mar 24 Python
结束运行python的方法
Jun 16 Python
python 偷懒技巧——使用 keyboard 录制键盘事件
Sep 21 Python
Python paramiko使用方法代码汇总
Nov 20 Python
详解Python中*args和**kwargs的使用
Apr 07 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 分页分组类
2009/12/10 PHP
php通过数组实现多条件查询实现方法(字符串分割)
2014/05/06 PHP
中高级PHP程序员应该掌握哪些技术?
2016/09/23 PHP
使javascript也能包含文件
2006/10/26 Javascript
javascript一点特殊用法
2008/05/28 Javascript
javascript 贪吃蛇实现代码
2008/11/22 Javascript
jQuery EasyUI API 中文文档 - ComboGrid 组合表格
2011/10/13 Javascript
FireFox下XML对象转化成字符串的解决方法
2011/12/09 Javascript
Android中资源文件(非代码部分)的使用概览
2012/12/18 Javascript
javaScript实现浮点数转十六进制字符
2013/10/29 Javascript
jQuery入门基础知识学习指南
2015/08/14 Javascript
三种方式实现瀑布流布局
2017/02/10 Javascript
Vue 2.X的状态管理vuex记录详解
2017/03/23 Javascript
深入理解react-router@4.0 使用和源码解析
2017/05/23 Javascript
bootstrap时间插件daterangepicker使用详解
2017/10/19 Javascript
js监听html页面的上下滚动事件方法
2018/09/11 Javascript
uni-app 组件里面获取元素宽高的实现
2019/12/27 Javascript
JQuery复选框全选效果如何实现
2020/05/08 jQuery
Node.js web 应用如何封装到Docker容器中
2020/09/01 Javascript
浅析python 内置字符串处理函数的使用方法
2014/06/11 Python
Django框架封装外部函数示例
2019/05/28 Python
python+openCV利用摄像头实现人员活动检测
2019/06/22 Python
Softmax函数原理及Python实现过程解析
2020/05/22 Python
python使用多线程+socket实现端口扫描
2020/05/28 Python
pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)
2020/06/24 Python
Scrapy模拟登录赶集网的实现代码
2020/07/07 Python
Ibood荷兰:互联网每日最佳在线优惠
2019/02/28 全球购物
元旦晚会感言
2014/03/12 职场文书
视光学专业自荐信
2014/06/24 职场文书
财务经理岗位职责范本
2015/04/08 职场文书
大学推普周活动总结
2015/05/07 职场文书
人与自然的观后感
2015/06/18 职场文书
小学开学典礼新闻稿
2015/07/17 职场文书
小学大队委竞选口号
2015/12/25 职场文书
六年级作文之自救
2019/12/19 职场文书
阿里云服务器搭建Php+Apache运行环境的详细过程
2021/05/15 PHP