python之yield
原创博客链接:python之yield
yield关键字之前见过,也能读懂,但开发时也不大敢使用,感觉理解还是不够充分。刚好项目代码中有涉及,顺便再学习学习。
在理解yield之前,
可迭代,迭代器,生成器
1 2 3 |
可迭代对象,是其内部实现了,__iter__ 这个魔术方法。 =>对比可迭代对象,迭代器其实就只是多了一个函数而已。就是__next__(),我们可以不再使用for循环来间断获取元素值。而可以直接使用next()方法来实现。 ==>生成器,则是在迭代器的基础上(可以用for循环,可以使用next()),再实现了yield。 |
可以看出三者存在明显递进关系,越往后要求越苛刻,需实现方法也越多.(如果分不清,查阅本文参考文献第一篇)
猜测代码结果
看如下代码
1 2 3 4 5 6 7 8 9 10 11 |
## 第一段代码 items=[i for i in range(10)] tmp=func(m)#func是一函数 print(func02(tmp))# func02是另一个函数 print(func02(tmp)) ## 第二段代码 items=[i for i in range(10)] tmp=func(m)#func是一函数 print(func02(func(m)))# func02是另一个函数 print(func02(func(m))) |
请问这二者输出相同么?如果不考虑前文的铺垫,孤零零放出这么一段代码,可能9成都会不假思索的说相同。因为第二段代码,其实就是把一个变量多定义几遍而已。
由于tmp=func(m),所以func02(tmp)等价于func02(func(m)),再结合软件开发中的业务逻辑确定性原则(同输入同输出),所以这两段代码输出必然相同。如果稍稍思考下就能发现,其实这个说法是有问题的,如果func02就是next()函数呢?显然输出会不同。
长久的编程习惯会让我们忽略一些东西,yield就属于忽略点,其内部等价于内置了”状态机”的概念。
如果对上面代码持有异议,可运行如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
def flatten(items, ignore_types=(str, bytes)):for x in items:if isinstance(x, Iterable) and not isinstance(x, ignore_types):yield from flatten(x)else:yield x 以下不同 tmp=flatten(items) print(next(flatten(items))) print(next(flatten(items))) print(next(flatten(items))) print(next(flatten(items)))tmp=flatten(items) print(next(tmp)) print(next(tmp)) print(next(tmp)) print(next(tmp)) |
yield简单介绍
yield 是什么东西呢,它相当于我们函数里的return。在每次next(),或者for遍历的时候,都会yield这里将新的值返回回去,并在这里阻塞,等待下一次的调用。记住要点,yield相关的2个动作和2个状态,return-自我阻塞-(别人)xx动作-唤醒(自己),完整就是,return之后,自动,自我阻塞,然后,等待xx的动作,唤醒自己。这个要记牢,否则后面容易懵。
如何创建一个生成器,主要有如下两种方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 01,使用列表生成式,注意不是[],而是() L = (x * x for x in range(10)) print(isinstance(L, Generator)) # True# 02,实现了yield的函数 def mygen(n):now = 0while now < n:yield nownow += 1if __name__ == '__main__':gen = mygen(10)print(isinstance(gen, Generator)) # True |
如何运行/激活生成器
1 2 |
使用next() 使用generator.send(None) |
这就是yield基础知识.
yield个人理解01,缓冲型(延迟型)list
就是把yield的函数看做普通list列表,不过是他什么时候用到什么时候计算,不关心他怎么实现的(或者什么时候真正执行的)。
这么理解,基本上大部分yield函数,看懂是没问题的,但是写呢?依然难以下手,因为不清楚每一行代码是如何运行的。 我之前就是这么理解的,阅读足够,开发不足。
yield个人理解02,多return时序函数
首先以下定义结构
1 |
yield x=>等价于=>return x,receive y |
举例:执行到yield时
连线1,返回。先return index,然后自我阻塞,
连线2,等待填充。y哪里其实是个空位,意味这等待外部向这里填充数据(如何填充?前面介绍的next or send).
连线3,填充后继续。填充数据之后,传递给yield index,中yield开始的位置,此处为=的右侧,所以receive后会赋值给jump
所以说yield的执行其实是”时序”型的,一个“时钟”就是一个next(or send),每走一步,return之后,等待,等别人通过next(or send),叫醒自己继续走.
从时间角度看,yield函数其实有”一系列不同时间的返回值”。
所以其非常适合”需要捕捉中间结果的迭代计算”
yield实例和分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
def jumping_range(N):index = 0while index < N:# 通过send()发送的信息将赋值给jumpjump = yield indexif jump is None:jump = 1index += jumpif __name__ == '__main__':itr = jumping_range(5)print(next(itr))print(itr.send(2))print(next(itr))print(itr.send(-1))输出: 0 2 3 2 |
分析:
如下图,粗黑线部分就是程序代码执行流,可见index=0这部分代码其实只执行了一次,后续每次next后程序起点都是Jump=xx
这种角度看,yield非常类似我们debug程序时加入的断点,断点处return 当前取值,然后set 新的取值.
胞兄yield from
简单的理解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 字符串 astr='ABC' # 列表 alist=[1,2,3] # 字典 adict={"name":"wangbm","age":18} # 生成器 agen=(i for i in range(4,8))def gen(*args, **kw):for item in args:# yield 方法for i in item:yield i# yield from方法#yield from itemnew_list=gen(astr, alist, adict, agen) print(list(new_list)) # ['A', 'B', 'C', 1, 2, 3, 'name', 'age', 4, 5, 6, 7] |
可以简单理解为
1 2 3 4 |
yield from item 等价于 for i in item:yield i |
委托生成器的作用是:在调用方与子生成器之间建立一个双向通道。
所谓的双向通道是什么意思呢?
调用方可以通过send()直接发送消息给子生成器,而子生成器yield的值,也是直接返回给调用方。
参考文献
Python并发编程之从生成器使用入门协程(七)
Python并发编程之深入理解yield from语法(八)
Python yield from 用法详解
python之yield相关推荐
- Python中yield和yield from的用法
yield 后面接的是 future 对象 调用方 委托生成器 yield from 直接给出循环后的结果 yield from 委托者和子生成器直接通信 yield from 直接处理stopIte ...
- [翻译]Python中yield的解释
问题: Python中yield关键字的作用是什么?它做了什么? 例如,我想理解以下代码 def node._get_child_candidates(self, distance, min_dist ...
- python中yield的认识与学习|生成器
接触python,yield就有点难度啦.都知道包含这个yield的函数就不是普通函数啦.就是一个生成器函数. 类型:<generator object test1 at 0x01D89220& ...
- js date 当前日志往后一个月_【应用实例】如何利用 Python 生成器 yield 监控日志?...
Python 生成器 yield 是编写基于处理管道,流或数据流程序的一种极其强大的方式,在<Python参考手册>中有一则实例非常简单实用,略加修改,分享一下给大家.如果你对生成器yie ...
- Python中yield简单用法
Python中yield简单用法 你或许知道带有yield的函数在Python中被称之为generator,那何为 generator? 我们暂时抛开generator,先从一个常见编程题目开始,循序 ...
- python 中 yield 的使用
python中yield在函数中的使用 正是因为函数含有这个yield,所以,该函数不再是普通的函数,而是生成器函数(generator function).下面通过小例子来说明一下这个内置函数的特性 ...
- [Python] 关键字 yield 用法详解
一个十分十分优秀的博客: python中yield的用法详解--最简单,最清晰的解释.
- python的yield是什么意思,python生成器是怎么使用的 python中yield是什么意思
python中return和yield怎么用的?两个有什么区别?你从未驯服过她,她只是在爱你的时候收起獠牙. yield yield是用于生成器.什么是生成器,你可以通俗的认为,在一个函数中,使用了y ...
- python中yield的用法(生成器的讲解)
2 理解说明yield与生成器 在Python中,使用yield的函数被称为生成器函数(generator function). 生成器有两种方法:next()和send(),都可以调用生成器 yie ...
最新文章
- linux各文件夹的作用域
- 结构体struct 联合体 union
- 你在过度测试你的软件吗?
- uos连接服务器共享文件夹,使用UOS系统共享文件给其他设备的的办法
- exchange 2013 lesson 4 - installing
- Android Handler、Loop 的简单使用
- freemarker 概述
- 200908阶段一C++多态
- Git之提示There is no tracking information for the current branch.
- android自定义键盘遮挡,Android软键盘遮挡的四种完美解决方案
- SQOOP 导出Hive数据到MySQL
- python difflib模块_Python一起来找茬—difflib模块
- 万年历显示c语言百度文库,C语言万年历
- 离线语音识别与语音转写初探
- 概念学习(学习笔记)
- C语言入夏标志,[二级C语言程序设计.docx
- 网络TCP/IP基础(IP地址与子网划分)
- Dilated Convolution + Receptive Field
- 微信证据以及数据恢复删除记录恢复交易恢复
- JAVA实现把PPT转PDF的方法
热门文章
- 【leveldb】整体架构
- 指针变量的声明、地址相关运算--“*”和“”
- java设计模式在线视频_Java设计模式之单例模式视频课程
- execution 排除_使用SQL Server 2016 Live Execution统计信息对SQL查询性能进行故障排除
- docker-machine create --driver virtualbox myvm1 创建失败
- 稳恒nb-iot模块WH-NB73 UDP透传和透传云使用说明
- Apache ActiveMQ教程
- Updatepanel 注册javascript 方法
- 图解 MongoDB 地理位置索引的实现原理
- 你不一定知道的vb6(2)