【Python】yield函数
【Python】yield函数
- 1. yield介绍
- 2.yield基本用法
- 3.yield高级用法
- 3.1 yield send() 方法
- 3.2 yield from方法
- 3.3 yield 和yield from叠加
- 处理复杂情况下的叠加
- 4.yield主要应用场景
- 5.总结
python官方api地址
1. yield介绍
在Python中,yield关键字主要用于生成器函数(generator functions)中,其目的是使函数能够像迭代器一样工作,即可以被遍历,但不会一次性将所有结果都加载到内存中。
2.yield基本用法
- 定义生成器函数
def simple_generator():yield 1yield 2yield 3gen = simple_generator()
print(next(gen)) # 输出: 1
print(next(gen)) # 输出: 2
print(next(gen)) # 输出: 3
- 使用 for 循环遍历生成器
生成器对象是可迭代的,因此可以使用 for 循环来遍历生成器生成的值。
下面例子中,for 循环遍历生成器函数生成的所有值,并依次打印它们。
def simple_generator():yield 1yield 2yield 3for value in simple_generator():print(value)
- 生成器表达式
下面例子中,生成器表达式生成了一个平方数序列,并使用 for 循环打印所有值。
gen_expr = (x * x for x in range(5))
for value in gen_expr:print(value)
- 生成器转列表
def simple_generator():yield 1yield 2yield 3
gen = simple_generator()
print(list(gen)) # 输出: [1, 2, 3]
3.yield高级用法
3.1 yield send() 方法
生成器不仅可以通过 yield 返回值,还可以通过 send() 方法接收外部输入。
send() 方法允许向生成器发送一个值,这个值将成为上一个 yield 表达式的值。
这种方式可以实现生成器与外部之间的双向通信。
def coroutine():while True:received = yieldprint(f"接收到的数据: {received}")co = coroutine()
next(co) # 预激生成器
co.send(10) # 输出: 接收到的数据: 10
co.send(20) # 输出: 接收到的数据: 20
在这个例子中,coroutine 生成器函数在每次迭代时接收外部数据并打印它。
next(co) 用于预激生成器,使其准备好接收数据。
3.2 yield from方法
从Python 3.3开始,引入了 yield from 语法,它允许一个生成器委托另一个生成器来生成值。
这种委托机制可以简化嵌套生成器的使用,提高代码的可读性和效率。
def base_code_pool():for i in range(3):yield f'BASE-{i + 1}'def outsource_pool():for i in range(30):yield f'OUTS-{i + 1}'def team_member_code():yield from base_code_pool()print('内部资源编号用完,开始使用外包')yield from outsource_pool()team_member = team_member_code()
for i in range(5):print(next(team_member))
运行结果:
BASE-1
BASE-2
BASE-3
内部资源编号用完,开始使用外包
OUTS-1
OUTS-2
在这个例子中,team_member_code 生成器函数委托 base_code_pool 和 outsource_pool 生成器来生成值。
当 base_code_pool 的值用完后,生成器会继续从 outsource_pool 生成值。
3.3 yield 和yield from叠加
yield 和 yield from 是 Python 中用于创建生成器的两种方式,它们允许函数在迭代过程中逐步返回值,而不是一次性返回所有结果。
这种特性使得生成器非常适合处理大型数据集或无穷序列等场景,因为它们不会一次性将所有数据加载到内存中,从而节省了内存资源。
关于是否可以“叠加”yield 和 yield from 的结果,实际上我们讨论的是如何组合多个生成器或者将一个生成器的结果传递给另一个生成器。
- 使用 yield 和 yield from 组合生成器
当你想要组合两个或更多个生成器时,你可以使用yield来逐个产出每个生成器中的元素,或者使用yield from来直接委托给子生成器,让其负责产出自己的元素。
例如:
def generator_a():for i in range(3):yield idef generator_b():for i in range(3, 6):yield idef combined_generators():# 使用 yield 直接产出每个生成器中的元素for value in generator_a():yield valuefor value in generator_b():yield value# 或者使用 yield from 委托给子生成器yield from generator_a()yield from generator_b()
在这个例子中,combined_generators 函数通过 yield 和 yield from 将两个生成器的结果进行了“叠加”。
这里,“叠加”的含义是指顺序地连接了两个生成器产生的输出流,而不是数学意义上的加法操作。
可以将 yield 和 yield from 结合使用来实现生成器之间的组合,甚至可以在同一个函数内部同时使用这两种语句。
这样做不仅可以简化代码结构,还能更灵活地控制生成器的行为。
让我们深入探讨一下如何有效地结合使用 yield 和 yield from 来“叠加”多个生成器的结果。
- 结果的实际叠加
如果我们谈论的是实际的结果叠加(如数值相加),那么你需要明确地编写逻辑来实现这一点。
比如,如果你想把来自不同生成器的数值相加以获得总和,你可以这样做:
def sum_of_generators(gen1, gen2):return sum(gen1) + sum(gen2)total = sum_of_generators(generator_a(), generator_b())
print(total) # 输出: 15 (0+1+2+3+4+5)
# 输出: 0 1 2 3 4 5
for item in combined_generators():print(item)
在这里,sum_of_generators 函数接收两个生成器作为参数,并分别对它们求和后再相加。
请注意,这种方法会立即消耗掉这两个生成器的所有元素并计算出总和,这可能不是最有效的做法,特别是对于非常大的数据集。
- 组合使用 yield 和 yield from
上面的例子可以将yield和yield from结合使用来实现生成器之间的组合,甚至可以在同一个函数内部同时使用这两种语句。
这样做不仅可以简化代码结构,还能更灵活地控制生成器的行为。
让我们深入探讨一下如何有效地结合使用yield和yield from来“叠加”多个生成器的结果。
考虑一个场景,你有一个主生成器,它需要从多个子生成器中获取值,并且自身也可能产生一些额外的值。
在这种情况下,你可以用yield来直接产出这些额外的值,而用yield from来委派给子生成器。
例如:
def generator_a():for i in range(3):yield idef generator_b():for i in range(3, 6):yield idef combined_generators():# 直接使用 yield 产出额外的值yield "Start"# 使用 yield from 委托给子生成器 ayield from generator_a()# 再次直接使用 yield 产出中间的值yield "Middle"# 使用 yield from 委托给子生成器 byield from generator_b()# 最后直接使用 yield 产出结束的值yield "End"# 输出: Start 0 1 2 Middle 3 4 5 End
for item in combined_generators():print(item)
在这个例子中,combined_generators 函数展示了如何在同一个生成器内混合使用 yield 和 yield from。
首先,它通过 yield 发出了字符串 "Start";
然后,利用 yield from 将控制权交给 generator_a(),后者负责产出 0, 1, 和 2;
接着,再次使用 yield 发出 "Middle";之后,又通过 yield from 让 generator_b() 产出 3, 4, 和 5;
最后,以同样的方式发出字符串 "End"。
这种方式允许你在不破坏原有逻辑的基础上轻松添加新的生成逻辑,同时也保持了代码的清晰度和可读性。
处理复杂情况下的叠加
如果你面对的是更加复杂的场景,比如你需要对来自不同生成器的数据进行某种形式的处理后再输出,或者你需要根据某些条件决定是否调用某个子生成器,那么你可以继续扩展这种模式。
例如,假设你想把两个生成器的结果相加后作为最终输出的一部分:
def add_generators(gen1, gen2):iterator1 = iter(gen1)iterator2 = iter(gen2)try:while True:value1 = next(iterator1)value2 = next(iterator2)yield value1 + value2except StopIteration:passdef enhanced_combined_generators():yield "Start"yield from add_generators(generator_a(), generator_b())yield "End"# 输出: Start 3 5 7 End
for item in enhanced_combined_generators():print(item)
综上所述,yield 和 yield from 的结果可以通过编程逻辑被“叠加”,但这取决于你想要实现的具体行为。
如果是简单的迭代输出,则可以直接使用 yield from 来简化代码;
而如果是数值或其他类型的累加,则需要额外的逻辑来完成这个过程。
4.yield主要应用场景
- 处理大数据集
生成器非常适合处理大数据集,因为它可以在需要时按需生成值,而不是一次性将所有值加载到内存中。
这可以显著减少内存使用,提高程序的性能。
def read_large_file(file_path):with open(file_path, 'r') as file:for line in file:yield linefor line in read_large_file('large_file.txt'):print(line, end='')
在这个例子中,生成器函数 read_large_file 逐行读取大文件,并使用 for 循环打印每行内容。
这种方法避免了将整个文件加载到内存中,从而节省了内存。
- 实现协程和并发
生成器可以用于实现协程和并发编程模式。
协程是一种用户态的轻量级线程,可以用来模拟异步操作,实现非阻塞的I/O处理等。
def coroutine_example():while True:received = yieldprint(f"处理数据: {received}")co = coroutine_example()
next(co) # 预激生成器
co.send('data1') # 输出: 处理数据: data1
co.send('data2') # 输出: 处理数据: data2
在这个例子中, coroutine_example 生成器函数可以接收外部数据并处理它,实现了简单的协程功能。
- 数据处理管道
生成器可以用于实现数据处理管道,每个生成器函数负责一个处理步骤。
这种模式可以将复杂的任务分解为多个简单的步骤,提高代码的可读性和可维护性。
def pipeline_stage1(data):for item in data:yield item * 2def pipeline_stage2(data):for item in data:yield item + 1data = range(5)
stage1 = pipeline_stage1(data)
stage2 = pipeline_stage2(stage1)for value in stage2:print(value)
在这个例子中,数据经过两个生成器函数处理。
首先在 pipeline_stage1 中乘以2,然后在 pipeline_stage2 中加1。
def add_generators(gen1, gen2):iterator1 = iter(gen1)iterator2 = iter(gen2)try:while True:value1 = next(iterator1)value2 = next(iterator2)yield value1 + value2except StopIteration:passdef enhanced_combined_generators():yield "Start"yield from add_generators(generator_a(), generator_b())yield "End"
# 输出: Start 3 5 7 End
for item in enhanced_combined_generators():print(item)这里定义了一个辅助函数 add_generators,它接受两个生成器并逐个取出它们的元素相加以生成新的值。enhanced_combined_generators 则是在之前的基础上加入了这个新功能。通过这种方式,你可以非常灵活地构建复杂的生成器逻辑,而不需要为每一个可能的变化都编写全新的生成器10。
综上所述,yield 和 yield from 可以很好地协同工作,帮助开发者构建高效、易于维护的生成器代码。无论是简单的串联还是更复杂的操作,如数据变换或条件分支,都可以通过合理的设计达到预期的效果。重要的是要理解每种语句的作用以及它们如何相互作用,这样才能写出既强大又优雅的 Python 代码2。此外,yield from 的引入不仅简化了代码,还增强了生成器之间通信的能力,特别是在涉及到异常传递时显得尤为重要14。因此,在实际编程实践中,充分利用这两种工具能够极大地提升代码的质量和性能。
5.总结
yield函数属性- 当一个函数包含yield关键字时,这个函数就变成了一个生成器函数。
- 调用生成器函数并不会立即执行函数体内的代码,而是返回一个生成器对象。
- 生成器对象可以被迭代,每次迭代时,生成器函数会从上次离开的地方继续执行,直到遇到下一个yield语句,然后返回一个值,并保存当前状态,以便下次继续执行。
- 这种行为使得生成器非常适合处理大量数据或流式数据,因为它不需要一次性将所有数据加载到内存中,从而节省了内存资源。
yieldvsreturnreturn:当函数执行到return语句时,它会立即停止执行,并返回一个值给调用。
这意味着函数的局部变量会被销毁,且函数的执行状态不会被保存。
因此,如果再次调用同一个函数,它将从头开始执行。yield:与return不同,当执行到yield语句时,函数会暂停执行,返回一个值给调用者,并保存当前的所有局部变量状态。
下次调用生成器时,函数将从上次暂停的地方恢复执行,直到遇到下一个yield语句或函数结束。
- 生成器的使用场景
- 处理大数据集:由于生成器是惰性求值的,它可以在需要时才生成数据,因此非常适合处理大数据集,避免了一次性加载所有数据导致的内存不足问题。
- 简化代码结构:使用生成器可以简化代码结构,尤其是当需要处理复杂的状态机或递归结构时。
- 协程与并发:虽然Python的标准库中已经提供了多种并发模型,但生成器可以作为一种轻量级的协程实现,用于实现简单的并发任务。
相关文章:
【Python】yield函数
【Python】yield函数 1. yield介绍2.yield基本用法3.yield高级用法3.1 yield send() 方法3.2 yield from方法3.3 yield 和yield from叠加处理复杂情况下的叠加 4.yield主要应用场景5.总结 python官方api地址 1. yield介绍 在Python中,yield关键字主要用于生成器函…...
Android13修改多媒体默认音量
干就完了! 设置音量为最大音量,修改如下: /framework/base/media/java/android/media/AudioSystem.java/** hide */public static int[] DEFAULT_STREAM_VOLUME new int[] {4, // STREAM_VOICE_CALL7, // STREAM_SYSTEM5, // STREAM_RING-5, // STREAM_MUSIC15, // STREAM…...
nginx+keepalived负载均衡及高可用
一、环境准备 主机名ip地址备注openEuler-1 192.168.121.11(本机) 192.168.131.11(心跳连接) nginx主负载均衡调度器openEuler-2 192.168.121.12(本机) 192.168.131.12(心跳连接) n…...
SP导入智能材质球
智能材质球路径 ...\Adobe Substance 3D Painter\resources\starter_assets\smart-materials 放入之后就会自动刷新...
Kotlin语言特性(一):空安全、扩展函数与协程
Kotlin语言特性(一):空安全、扩展函数与协程 一、引言 Kotlin作为Android官方推荐的开发语言,相比Java具有诸多现代化特性。本文将重点介绍Kotlin三个最具特色的语言特性:空安全、扩展函数和协程,并结合A…...
Sqlserver安全篇之_启用TLS即配置SQL Server 数据库引擎以加密连接
官方文档 https://learn.microsoft.com/zh-cn/sql/database-engine/configure-windows/configure-sql-server-encryption?viewsql-server-ver16 https://learn.microsoft.com/zh-cn/sql/database-engine/configure-windows/manage-certificates?viewsql-server-ver15&pre…...
Python 爬虫 – BeautifulSoup
Python 爬虫(Web Scraping)是指通过编写 Python 程序从互联网上自动提取信息的过程。 爬虫的基本流程通常包括发送 HTTP 请求获取网页内容、解析网页并提取数据,然后存储数据。 Python 的丰富生态使其成为开发爬虫的热门语言,特…...
【星云 Orbit-STM32F4】07. 用判断数据尾来接收据的串口通用程序框架
【星云 Orbit-STM32F4】用判断数据尾来接收一串数据的串口通用程序框架 摘要 本文介绍了一种基于STM32F407微控制器的串口数据接收通用程序框架。该框架通过判断数据尾来实现一串数据的完整接收,适用于需要可靠数据传输的应用场景。本文从零开始,详细讲…...
授权与认证之jwt(一)创建Jwt工具类
JWT的Token要经过加密才能返回给客户端,包括客户端上传的Tokn,后端项目需要验证核 实。于是我们需要一个WT工具类,用来加密Token和验证Token的有效性。 一、导入依赖 <dependency><groupId>com.auth0</groupId><artifactId>jav…...
Kubernetes Service服务发现dns之CoreDNS
文章目录 背景什么是Service、服务发现、Endpoint什么是CoreDNSCoreDNS 的工作原理 常用命令coredns 运行状态根据服务名,判断某个服务dns解析是否正常 背景 Kubernetes 集群内部的服务发现是微服务架构的核心基础,而 DNS 服务则是实现这一机制的关键组…...
Spring Boot 测试:单元、集成与契约测试全解析
一、Spring Boot 分层测试策略 Spring Boot 应用采用经典的分层架构,不同层级的功能模块对应不同的测试策略,以确保代码质量和系统稳定性。 Spring Boot 分层架构: Spring Boot分层架构 A[客户端] -->|HTTP 请求| B[Controller 层] …...
用友NC系列漏洞检测利用工具
声明!本文章所有的工具分享仅仅只是供大家学习交流为主,切勿用于非法用途,如有任何触犯法律的行为,均与本人及团队无关!!! 目录标题 YongYouNcTool启动及适配环境核心功能界面预览一键检测命令执…...
PostgreSQL 创建表格
PostgreSQL 创建表格 在数据库管理中,表格(Table)是数据存储的基础。PostgreSQL作为一款强大的开源对象关系型数据库管理系统(ORDBMS),创建表格是其最基本的功能之一。本文将详细讲解如何在PostgreSQL中创…...
一周一个Unity小游戏2D反弹球游戏 - 球的死区及球重生
前言 本文将实现当球弹到球板下方的死亡区域后,球会被重置到球板上发射点,并且重置物理状态的逻辑。 创建球的死亡区 之前创建的在屏幕下方的空气墙碰撞体可以将其Is Trigger勾选上,让其成为一个触发器,用来检测球是否进入该区域,如下。 创建一个脚本名为Deadzone…...
本地部署 DeepSeek:从 Ollama 配置到 Spring Boot 集成
前言 随着人工智能技术的迅猛发展,越来越多的开发者希望在本地环境中部署和调用 AI 模型,以满足特定的业务需求。本文将详细介绍如何在本地环境中使用 Ollama 配置 DeepSeek 模型,并在 IntelliJ IDEA 中创建一个 Spring Boot 项目来调用该模型…...
vue3:三项目增加404页面
一、路由添加 1、官网地址 带参数的动态路由匹配 | Vue Routerhttps://router.vuejs.org/zh/guide/essentials/dynamic-matching.html 2、复制核心语句 { path: /:pathMatch(.*)*, name: NotFound, component: NotFound } 3、粘贴到路由index.js中 4、建立页面 在view文件夹…...
MCAL(Microcontroller Abstraction Layer)介绍
目录 MCAL的核心作用 MCAL的模块组成 1. 微控制器驱动(Microcontroller Drivers) 2. I/O驱动(DIO, PWM, ADC等) 3. 通信驱动(Communication Drivers) 4. 存储驱动(Memory Drivers…...
爬虫:PhantomJS的详细使用和实战案例
文章目录 一、PhantomJS介绍1.1 什么是 PhantomJS1.2 PhantomJS 的特点与优势二、PhantomJS 的安装2.1 在 macOS 上安装 PhantomJS2.2 在 Linux 上安装 PhantomJS2.3 在 Windows 上安装 PhantomJS2.4 验证安装三、PhantomJS 的基本使用3.1 示例 1:打开网页并截图3.2 示例 2:获…...
目标检测——数据处理
1. Mosaic 数据增强 Mosaic 数据增强步骤: (1). 选择四个图像: 从数据集中随机选择四张图像。这四张图像是用来组合成一个新图像的基础。 (2) 确定拼接位置: 设计一个新的画布(输入size的2倍),在指定范围内找出一个随机点(如…...
深度学习工程师的技术图谱和学习路径
在构建一个深度学习工程师的技术图谱时,按照“技能树与能力模型”的结构可以帮助清晰地展示出技术体系的层次化关系,帮助学习者更好地理解每个技术点的依赖与顺序。 深度学习工程师的技术图谱和学习路径 以下是深度学习工程师的技能树,包括从基础到进阶的学习路径,以及对…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
