详解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 22 Python
python实现批量按比例缩放图片效果
Mar 30 Python
通过Py2exe将自己的python程序打包成.exe/.app的方法
May 26 Python
Python实现的特征提取操作示例
Dec 03 Python
Python生成一个迭代器的实操方法
Jun 18 Python
python通过robert、sobel、Laplace算子实现图像边缘提取详解
Aug 21 Python
python如何保证输入键入数字的方法
Aug 23 Python
Python中 CSV格式清洗与转换的实例代码
Aug 29 Python
对python中arange()和linspace()的区别说明
May 03 Python
Python 忽略文件名编码的方法
Aug 01 Python
Python+Selenium随机生成手机验证码并检查页面上是否弹出重复手机号码提示框
Sep 21 Python
五分钟学会怎么用python做一个简单的贪吃蛇
Jan 12 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 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法
2013/09/28 PHP
文件上传之SWFUpload插件(代码)
2015/07/30 PHP
四个PHP非常实用的功能
2015/09/29 PHP
PHP有序表查找之插值查找算法示例
2018/02/10 PHP
PDO::query讲解
2019/01/29 PHP
jQuery 方法大全方便学习参考
2010/02/25 Javascript
js 限制数字 js限制输入实现代码
2012/12/04 Javascript
jquery实现人性化的有选择性禁用鼠标右键
2014/06/30 Javascript
javascript中为某个元素指定事件的三种方式
2014/08/07 Javascript
Jquery通过JSON字符串创建JSON对象
2014/08/24 Javascript
jQuery实现新消息在网页标题闪烁提示
2015/06/23 Javascript
jQuery实现微信长按识别二维码功能
2016/08/26 Javascript
jquery 动态增加,减少input表单的简单方法(必看)
2016/10/12 Javascript
微信小程序搜索组件wxSearch实例详解
2017/06/08 Javascript
React学习笔记之事件处理(二)
2017/07/02 Javascript
使用svg实现动态时钟效果
2018/07/17 Javascript
JavaScript中将值转换为字符串的五种方法总结
2019/06/06 Javascript
Vue-router中hash模式与history模式的区别详解
2020/12/15 Vue.js
python爬虫 正则表达式使用技巧及爬取个人博客的实例讲解
2017/10/20 Python
python机器学习之贝叶斯分类
2018/03/26 Python
PyQt5每天必学之像素图控件QPixmap
2018/04/19 Python
Python 改变数组类型为uint8的实现
2020/04/09 Python
Python Socket多线程并发原理及实现
2020/12/11 Python
详解快速开发基于 HTML5 网络拓扑图应用
2018/01/08 HTML / CSS
努比亚手机官网:nubia
2016/10/06 全球购物
澳大利亚拥有最佳跳伞降落点和最好服务的跳伞项目运营商:Skydive Australia
2018/03/05 全球购物
弘扬职业精神演讲稿
2014/03/20 职场文书
个人自我鉴定总结
2014/03/25 职场文书
培训协议书范本
2014/04/22 职场文书
关于教师节的演讲稿
2014/09/04 职场文书
2015年秋季新学期寄语
2015/03/25 职场文书
学校元旦晚会开场白
2015/05/29 职场文书
回复函格式及范文
2015/07/14 职场文书
安全教育日主题班会
2015/08/13 职场文书
七年级作文之下雨天
2019/12/23 职场文书
Python内置数据结构列表与元组示例详解
2021/08/04 Python