【Python】一篇文章读懂yield基本用法
这一次,田辛老师想通俗易懂地解释一下Python中的yield功能。
本文要说明以下四个问题:
- yield是什么
- 什么是迭代器和生成器
- yield的基本用法
- 如何使用
yield from
用真正简单的方法讲解yield
并不容易。 我想,就算你不懂yield
语句,也能从我的文档中有所收获。 这篇文章为了让读者理解,举了一个未必特别恰当的例子。 不过例子只是例子,重要的是了解原理。
本文要求环境版本高于Python3.7以上。
1. yield
是什么?
yield
是一种能够暂时中止函数执行的语句。
您可以用它返回此时的返回值并重新启动。 要了解yield
, 你必须了解迭代器和生成器。
ps. 这两句话目前不理解没关系, 后面的例子我们会反复解读这两句话
2. 什么是迭代器和生成器
迭代器:是一种可以迭代以检索元素的类型。 Python的下面list、dict、tuples都可以迭代的,所以这些对象就是迭代器。
生成器:生成器通过每次取出元素执行处理来生成元素。
这里田辛老师先大致说一句为什么yield
这么重要:迭代器在创建可迭代对象的时候, 并不是一次性生成的。 比如我们现在需要一些员工编号的list,如果不用yield
,通常的做法,我们生成一个list,内容是完整的员工编号1-100。 通常是一次性生成,此时内存中就有一个包含着1-100这100个数字的列表。
通常情况下这没什么问题。 但是,一旦我们列表中的内容非常占用内存。 在大数据场景下消耗资源特别大的时候,这就会影响我们程序执行效率以及设备的负荷。 如果你使用了yield
,这就会好很多。 yield
的机制并不会生成一个1-100的序列在那里占内存。 而是只有生成器在要求的时候,这个值才会被生成,而且用过即焚,不用空占内存。
好了,先了解到这里。如果你不理解,我们一边用一边理解。
3. yield
的基本用法
3.1 编写迭代器
yield 基本上是函数内部使用的语句。 基本语法是: yield <value>
我们举一个员工的例子,我们做一个基础编号池,为了简单,这里我给基础编号池3个编号。 这实际上就是迭代器。
def base_code_pool():"""BASE编号池 1-3 """for i in range(3):yield 'BASE-%s' % str(i + 1)
那么这个迭代器怎么使用呢? 还记得田辛老师在最开始的时候说:”yield
是一种能够暂时中止函数执行的语句。您可以用它返回此时的返回值并重新启动。“
也就是我们必须用生成器生成,迭代器才有意义。
3.2 编写生成器
那么我们来做写这个生成器:
gen = base_code_pool()
就这么简单,一行代码,那么如何使用呢?
print(next(gen))
print(next(gen))
print(next(gen))
有了迭代器,有了生成器, 那么我们3次请求这个编号池,输出结果就是:
BASE-1
BASE-2
BASE-3
[Finished in 167ms]
可以看到,每次执行都会产生一个新的编号。
但是这里要注意:迭代器里面多少个元素,就只能请求多少次。 多了会报错。
比如我们再多请求一次。 也就是在刚才的print
代码的部分写四个print(next(gen))
,你会发现前三个正确表示,第四个会报错。田辛老师的执行结果:
BASE-1
BASE-2
BASE-3
Traceback (most recent call last):File "D:\develop\python\di08-tdd-cdg-python-learning\src\adv_yield\yield_test.py", line 12, in <module>print(next(gen))
StopIteration
[Finished in 172ms]
这一点要牢记。
这里要说一个小故事, 事实上,Python3及更早版本中存在一个next()
函数, 只不过已经消失。取而代之的是引入了__next__()
方法。看到这个方法的名字我们就知道这是一个特殊方法。 特殊方法在一般程序中大量调用肯定不太好。 于是Python后来的版本又提供了一个next的内置函数。 现在的next()
函数是调用的__next__()
方法。 所以,现在的next()
并非更早期的next()
为了证明这点,我么再举一个例子,还是刚才的BASE迭代器,只不过在使用生成器的时候,这么写:
gen = base_code_pool()print(gen.__next__()) # 证明了`next()`函数和`__next__()`方法的关系
print(list(gen)) # 证明"BASE-1"已经被释放掉了
这样的执行结果是:
BASE-1
['BASE-2', 'BASE-3']
[Finished in 157ms]
这里,我们首先证明了next()
函数和__next__()
方法的关系。 另外,注意,我们在生成了一个编号后,列出了剩下的全部编号。 你会发现, "BASE-1"并不在这个list里面, 为什么呢? 因为用后即焚,"BASE-1"已经被释放掉了。 这也就是我们一直强调yield
非常节省内存的原因!
4. 关于yield from
现在我们已经学会了如何使用基本的yield
,让我们来谈谈yield from
。
yield from
主要用于将生成器拆分成更小的部分。这是从 Python 3.3 添加的语法,所以它不能在早期版本中使用。
比如刚才的编号是你项目组组员的编号。 公司就给了你三个资源的名额,并且说:人不够就使用外包。 那么在这种情况下, 你的生成器可以做一些调整来适应这个情况。
首先,外包人员也需要一个迭代器:
def outsource_pool():"""外包编号池:OUTS 1-30"""for i in range(30): # 好吧,给了你30个外包的名额yield 'OUTS-%s' % (i + 1)
现在我们有了两个编号池, 我们的原则是先用BASE,BASE的编号用完了以后,就用OUTS。 那么这个逻辑怎么优雅的实现呢? 下面就用到了 yield from
, 参考下面代码
def team_member_code():"""team_member迭代器"""yield from base_code_pool()print('内部资源编号用完,开始使用外包')yield from outsource_pool()
我们写了一个team_member_code()
迭代器, 这个迭代器里面有两个小迭代器, base写在上面, 外包写在下面。 OK, 我们来调用一下,看看执行结果
team_member = team_member_code()
print(next(team_member))
print(next(team_member))
print(next(team_member))
print(next(team_member))
print(next(team_member))
执行结果是:
BASE-1
BASE-2
BASE-3
内部资源编号用完,开始使用外包
OUTS-1
OUTS-2
[Finished in 138ms]
那么这样,我们就简单的实现了我们刚才组织资源用完了,用外包的需求。
而且这里也证明了,实际上迭代器的执行过程是在yield
的位置中断的。 所以“资源用完”的提示才会出现在子迭代器切换的位置。
我们来试试直接list:print(list(team_member_code()))
, 目的是一次性列出所有编号。
输出结果:
内部资源编号用完,开始使用外包
['BASE-1', 'BASE-2', 'BASE-3', 'OUTS-1', 'OUTS-2', 'OUTS-3', 'OUTS-4', 'OUTS-5', 'OUTS-6', 'OUTS-7', 'OUTS-8', 'OUTS-9', 'OUTS-10', 'OUTS-11', 'OUTS-12', 'OUTS-13', 'OUTS-14', 'OUTS-15', 'OUTS-16', 'OUTS-17', 'OUTS-18', 'OUTS-19', 'OUTS-20', 'OUTS-21', 'OUTS-22', 'OUTS-23', 'OUTS-24', 'OUTS-25', 'OUTS-26', 'OUTS-27', 'OUTS-28', 'OUTS-29', 'OUTS-30']
[Finished in 172ms]
我们可以看到, 如果直接list()
,“资源用完”这句话出现的位置,也说明了他的执行过程。
***特别声明:这个和实际场景有出入,田辛老师作为做了很多年外包项目,也管理了很多年带有外包的团队的IT老兵,没有对外包的同学任何轻视。 这里只是个例子。 ***
5. 总结
本文记录的实际上是yield
的最基础知识。 yield
的基础知识点可以归纳为
- 迭代器和生成器
- 用
yield
时,重复处理使用的内存更少 - 在
for
循环中处理或使用生成器的next()
函数 - 可以利用
yield from
将一个迭代器划分为多个小迭代器,从而进行精细化处理。
6. 代码
老规矩,所有的过程代码附上:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
#-----------------------------------------------------------------------------
# --- TDOUYA STUDIOS ---
#-----------------------------------------------------------------------------
#
# @Project : di08-tdd-cdg-python-learning
# @File : yield_test.py
# @Author : tianxin.xp@gmail.com
# @Date : 2023/2/12 21:57
#
# 用于整理yield使用教学的测试代码
#
#--------------------------------------------------------------------------"""def base_code_pool():"""BASE编号池 1-3 """for i in range(3):yield 'BASE-%s' % str(i + 1)# gen = base_code_pool()# print(next(gen))
# print(next(gen))
# print(next(gen))
# print(next(gen))# print(gen.__next__())
# print(list(gen))def outsource_pool():"""外包编号池:OUTS 1-30"""for i in range(30): # 好吧,给了你30个外包的名额yield 'OUTS-%s' % (i + 1)def team_member_code():"""team_member迭代器"""yield from base_code_pool()print('内部资源编号用完,开始使用外包')yield from outsource_pool()# team_member = team_member_code()# print(next(team_member))
# print(next(team_member))
# print(next(team_member))
# print(next(team_member))
# print(next(team_member))print(list(team_member_code()))
相关文章:
【Python】一篇文章读懂yield基本用法
这一次,田辛老师想通俗易懂地解释一下Python中的yield功能。 本文要说明以下四个问题: yield是什么什么是迭代器和生成器yield的基本用法如何使用yield from 用真正简单的方法讲解yield并不容易。 我想,就算你不懂yield语句,也…...
Docker getting started
系列文章目录 Docker 概述 Docker getting started 文章目录系列文章目录前言一、容器及镜像的概念二、容器化一个应用三、更新应用四、分享应用五、持久化数据存储volume mount 和 bind mount比较Container volumesbind mounts六、跨多容器的应用七、Docker 其它八、Docker 图…...
【Uniapp使用遇到问题合集】
Uniapp使用遇到问题合集问题一跳转页面后无法进行滑动/滚动的操作描述解决方法问题一 跳转页面后无法进行滑动/滚动的操作 描述 如题,实际操作是我在uniapp自带的组件uni-popup弹出层中加入了一个点击事件,点击后可跳转到指定的页面 但实际运行中出现了跳转过后页面过长时无…...
宝塔面板破解最新教程
宝塔,让运维简单高效。面板支持Linux与Windows系统。一键配置:LAMP/LNMP、网站、数据库、FTP、SSL,通过Web端轻松管理服务器。今天考高分网就简单说一下BT宝塔面板专业版最新破解教程。 网地址:https://www.bt.cn/ 网上的破解版一般分为两种,一种是直接…...
基于zookeeper的Hadoop集群搭建详细步骤
目录 一、一些基本概念 二、集群配置图 三、Hadoop高可用集群配置步骤 1.在第一台虚拟机解压hadoop-3.1.3.tar.gz到/opt/soft/目录 2.修改文件名、属主和属组 3.配置windows四台虚拟机的ip映射 4.修改hadoop配置文件 (1)hadoop-env.sh (2)workers (3)crore-site.xml …...
职称有哪些意义?如何提升职称?
每年我们会看到很多人都会努力地提升自己的职称,那么为什么大家都想要晋升职称?在这里余老师说说他的作用,您可以参考一下。 一、个人金钱方面的提升 工资。职称直接关联的就是涨工资了。正常情况下,职称和工资是一一对应的了,…...
mulesoft MCIA 破釜沉舟备考 2023.02.15.09
mulesoft MCIA 破釜沉舟备考 2023.02.15.09 1. According to MuleSoft, which deployment characteristic applies to a microservices application architecture?2. Refer to the exhibit.3. Mule application A receives a request Anypoint MQ message REQU with a payload…...
【项目实战】@ConditionalOnProperty注解让我少写了一些if判断
一、需求说明 本机启动含有XXL-job的工程,发现每次都会进行XXL-job的init的动作。这会导致本机每次启动都会把自己注册到XXL-job的服务端。但是我明明本地调试的功能不想要是编写定时任务,于是想了下,是否可以设计一个开关,让本机…...
SQL中的游标、异常处理、存储函数及总结
目录 一.游标 格式 操作 演示 二.异常处理—handler句柄 格式 演示 三.存储函数 格式 参数说明 演示 四.存储过程总结 一.游标 游标(cursor)是用来存储查询结果集的数据类型,在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、OPEN、…...
Splashtop:支持M1/M2芯片 Mac 电脑的远程控制软件
M1和M1芯片的Mac电脑现在越来越多了。M1和M2的强大性能,让使用者们办公、娱乐如虎添翼。 M1 芯片于2020年11月11日推出,是Apple 首款专为Mac打造的芯片,拥有格外出色的性能、众多的功能,以及令人惊叹的能效表现。M1 也是Apple 首款…...
实验十三、阻容耦合共射放大电路的频率响应
一、题目 利用 Multism 从以下几个方面研究图1所示的阻容耦合共射放大电路的频率响应。图1阻容耦合共射放大电路图1\,\,阻容耦合共射放大电路图1阻容耦合共射放大电路(1)设 C1C210μFC_1C_210\,\textrm{μF}C1C210μF,分别测试它们所确定…...
【每天进步一点点】函数表达式和函数声明
函数声明 function 函数名(){} 函数声明会被率先读取。 函数声明后不会立即执行,会在我们需要的时候调用到。 由于函数声明不是一个可执行语句,所以不以分号结束。 函数表达式 表达式赋值给了一个变量 const 变量名 functi…...
JavaScript void
文章目录JavaScript voidjavascript:void(0) 含义href"#"与href"javascript:void(0)"的区别JavaScript void javascript:void(0) 含义 我们经常会使用到 javascript:void(0) 这样的代码,那么在 JavaScript 中 javascript:void(0) 代表的是什么…...
笔记本电脑怎么连接无线网wifi?不同电脑系统的使用教程(2023最新)
现在越多人使用笔记本电脑,在我们的日常生活和工作中是很难离开它的。想要更快速地上网,我们都会选择连接无线网的wifi。有时笔记本电脑无法连接网络,你知道这是什么原因吗?笔记本电脑怎么连接无线网wifi?方法很简单&a…...
从lettcue插件看skywalking
lettcue 的写操作是异步的。io.lettuce.core.RedisChannelWriter.write进行写入,io.lettuce.core.protocol.RedisCommand进行异步读取数据 skywalking 插件大体逻辑 在方法执行前,通过ContextManager创建span创建span的同时,判断trace上下文…...
explain 每个列的含义
官网传送门:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html 实例表 DROP TABLE IF EXISTS actor;CREATE TABLE actor (id int(11) NOT NULL,name varchar(45) DEFAULT NULL,update_time datetime DEFAULT NULL,PRIMARY KEY (id)) ENGINEInnoDB DEFA…...
网络通信编程基础
1.IP地址 概念 IP地址主要用于标识网络主机、其他网络设备(如路由器)的网络地址。简单说,IP地址用于定位主机的网络地址。 就像我们发送快递一样,需要知道对方的收货地址,快递员才能将包裹送到目的地。 格式 IP地址…...
Linux网络编程
一、网络结构模式 1、C/S 结构 1)、简介 服务器 - 客户机,即 Client - Server(C/S)结构。C/S 结构通常采取两层结构。服务器负责数据的管理,客户机负责完成与用户的交互任务。客户机是因特网上访问别人信息的机器&a…...
***httpGet,httpPost,postman_http,httpClientSocket,httpSocketServer***
1:状态码_http 2:java访问(http):国家气象局 免费接口 3:httpClientSocket ~~~ httpSocketServer 4:httpGet ~ httpPost 1:状态码_http http请求的响应码一般分为五类 1xx 2xx 3xx 4xx 5xx 1xx 临时性的消息 101:当客户端问服务端支不支持http2.0的时候,如果支持服…...
Downie4.6.7
Downie是Mac下一个简单的下载管理器,可以让您快速将不同的视频网站上的视频下载并保存到电脑磁盘里然后使用您的默认媒体播放器观看它们,文章末尾附下载地址。主要特点支持许多网站目前支持超过1,000个不同的网站(包括YouTube,Vim…...
重构是什么
重构 重构的主要目的是解决技术债务问题。它将混乱的代码转化为清晰的代码和简单的设计。 不错!但是“清晰的代码”具体是什么呢?以下是它的一些特征: 清晰的代码对其他程序员来说应该是一目了然的。 我不是在谈论超级复杂的算法。糟糕的…...
(考研湖科大教书匠计算机网络)第四章网络层-第六节1:路由选择协议概述
获取pdf:密码7281专栏目录首页:【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一:路由选择概述二:因特网采用的路由选择协议(1)特点(2)常见的路由选择协议三:…...
vue2源码之生命周期篇
vue2源码之生命周期篇vue2源码之生命周期篇生命周期流程图初始化阶段(new Vue)vue2源码之生命周期篇 生命周期流程图 从图中可以看到,Vue实例的生命周期大致可分为4个阶段: 初始化阶段:为Vue实例上初始化一些属性&am…...
从零实现WebRTC(三):WebRTC中重要的API
文章目录一、createOffer二、createAnswer三、SetLocalDescription四、SetRemoteDescription五、addTrack六、addCandidate七、RTCPeerConnection重要事件一、createOffer aPromise myPeerConnection.createOffer(option) opeion { Audio True, Video True, iceReStart:f…...
shell脚本的编写以及shell中语句(嵌入式学习)
shell学习shell脚本编写步骤shell变量功能性语句1.read2.expr3.let4.test逻辑运算符的书写格式结构性语句1.if…then…fi2、case...esac3、for..do..done4、while..do..doneshell脚本 将shell命令按照一定的逻辑顺序实现指定功能,放到一个文件中。文件叫脚本文件&a…...
2023年高新技术企业怎么申报认定
成为高新技术企业可以获得国家和本地区的众多优惠政策,相信很多企业都想申请高企认定,国家高新技术企业又称国家高新技术企业,根据《高新技术企业认定管理办法》规定,国家高新技术企业是指在《国家重点支持的高新技术领域》内&…...
GIS状态检测新技术——振动分析法
提示:唐老师好,我之前因为“阳”了,所以就没有参与汇报,给老师带来不便,请老师见谅。以此篇文章代替课堂汇报。 文章目录前言一、不同故障对应的振动频谱和故障特征量二、GIS设备振动特征估计1.GIS设备状态空间2.粒子滤…...
Python进阶篇(一)-- Django快速上手
1 Django概述 Web框架,就是用于开发Web服务器端应用的基础设施,说得通俗一点就是一系列封装好的模块和工具。事实上,即便没有Web框架,我们仍然可以通过socket或CGI来开发Web服务器端应用,但是这样做的成本和代价在商业…...
读书笔记//来自公众号(1)
——【9大数据分析方法】—— 总结1:多部分方法用于定位问题,相关分析法与指标拆解法可以解释问题。 总结2:抓住两个关键因素:维度(类别)、指标 一、周期性分析 1.常见的周期包括2种:自然周期…...
10款让程序员用了会上瘾的工具
程序员必定会爱上的10款工具,相信肯定有不少是你的心头好,尤其是第4款。 第一款:TrueCryptTrueCrypt 可能很多人没用过,它是一个加密软件,能够对磁盘进行加密。还在担心自己电脑中的重要文件、私密档案被人查看&…...
做网站网页尺寸是多少钱/网站优化外包公司
三、LINPUT输入通道介绍 有关LINPUT的主要配置如下: R32的bit8(LMN1)置1:LINPUT1连接PGA; R00的bit7(LINMUTE)置0:禁止静音; R25的bit5(AINL)置1:PGA使能; R47的bit5(LMIC)置1:Left …...
wordpress自带相册/营销策略从哪几个方面分析
目录 前言 一、词向量基础 1.单词的表示 2.从独热编码到分布式表示 3.词向量的训练 二、SkipGram模型详解 1.训练词向量的核心思想 2.SkipGram的目标函数 3.SkipGram的负采样 三、其他词向量技术 1.矩阵分解法 2.Glove向量 总结 前言 上一章已经介绍完自然语言处…...
做网站全屏尺寸是多少/安阳seo
根据EDIP的flg文件生成测试数据。 30张表,一个表1亿,而且要生成在硬盘而不是hdfs,但直接生成在硬盘就用不了spark了,所以先生成在hdfs,然后下载到硬盘,为了防止hdfs空间不足,暂时先把hdfs的副本…...
做欧洲电商看哪个网站吗/系统优化的方法
由于阅读内核时经常遇到各种各样的锁,以前没去太在意它们,终于忍不住了,决心把内核中的锁搞清楚。 为了使并发程度达到最大,不同的情况下需要使用不同的锁,在了解各种锁之前,需要先搞清两个很容易混淆的概念…...
ss网站代码/知乎推广
线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态及死亡状态。 1.新建状态(New): 当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在…...
用wordpress做的网站有哪些/百度账号快速注册
python爬虫可以用来做什么?1、收集数据python爬虫程序可用于收集数据。这也是最直接和最常用的方法。由于爬虫程序是一个程序,程序运行得非常快,不会因为重复的事情而感到疲倦,因此使用爬虫程序获取大量数据变得非常简单和快速。由…...