【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叠加

yieldyield 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 函数通过 yieldyield from 将两个生成器的结果进行了“叠加”。
这里,“叠加”的含义是指顺序地连接了两个生成器产生的输出流,而不是数学意义上的加法操作。
可以将 yieldyield from 结合使用来实现生成器之间的组合,甚至可以在同一个函数内部同时使用这两种语句。
这样做不仅可以简化代码结构,还能更灵活地控制生成器的行为。
让我们深入探讨一下如何有效地结合使用 yieldyield 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
    上面的例子可以将 yieldyield from 结合使用来实现生成器之间的组合,甚至可以在同一个函数内部同时使用这两种语句。
    这样做不仅可以简化代码结构,还能更灵活地控制生成器的行为。
    让我们深入探讨一下如何有效地结合使用 yieldyield 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 fromgenerator_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)

综上所述,yieldyield 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语句,然后返回一个值,并保存当前状态,以便下次继续执行。
    • 这种行为使得生成器非常适合处理大量数据或流式数据,因为它不需要一次性将所有数据加载到内存中,从而节省了内存资源。
  • yield vs return
    • return:当函数执行到return语句时,它会立即停止执行,并返回一个值给调用。
      这意味着函数的局部变量会被销毁,且函数的执行状态不会被保存。
      因此,如果再次调用同一个函数,它将从头开始执行。
    • yield:与return不同,当执行到yield语句时,函数会暂停执行,返回一个值给调用者,并保存当前的所有局部变量状态。
      下次调用生成器时,函数将从上次暂停的地方恢复执行,直到遇到下一个yield语句或函数结束。
  • 生成器的使用场景
    • 处理大数据集:由于生成器是惰性求值的,它可以在需要时才生成数据,因此非常适合处理大数据集,避免了一次性加载所有数据导致的内存不足问题。
    • 简化代码结构:使用生成器可以简化代码结构,尤其是当需要处理复杂的状态机或递归结构时。
    • 协程与并发:虽然Python的标准库中已经提供了多种并发模型,但生成器可以作为一种轻量级的协程实现,用于实现简单的并发任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/21092.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习实战(1): 入门——什么是机器学习

机器学习入门——什么是机器学习? 欢迎来到“机器学习实战”系列的第一篇博文!在这一集中,我们将带你了解机器学习的基本概念、主要类型以及它在现实生活中的应用。无论你是初学者还是有一定经验的开发者,这篇文章都会为你打下坚…

华为IPD简介

创作灵感 现在“熟悉华为IPD”经常出现在高级招聘岗位能力要求上,于是作者写下此文章以此巩固相关知识储备 名词解释 华为IPD(Integrated Product Development,集成产品开发)是华为引入并优化的一套产品开发管理体系&#xff0…

Git备忘录(三)

设置用户信息: git config --global user.name “itcast” git config --global user.email “ helloitcast.cn” 查看配置信息 git config --global user.name git config --global user.email $ git init $ git remote add origin gitgitee.com:XXX/avas.git $ git pull or…

智能体(AI Agent、Deepseek、硅基流动)落地实践Demo——借助大模型生成报表,推动AI赋能企业决策

文章目录 一、 引言二、 系统设计与技术细节2.1 系统架构2.2 核心组件说明 三、 Demo 代码推荐博客: 四、输出年度营销报告1. 总销售额 根据提供的数据,年度总销售额为:740.0。2. 各产品销售额3. 各地区销售额4. 各产品在各地区的销售情况 分…

半遮挡检测算法 Detecting Binocular Half-Occlusions

【1. 背景】: 本文分析【Detecting Binocular Half-Occlusions:Empirical Comparisons of Five Approaches】Geoffrey Egnal和Richard P. Wildes于2002年发表在IEEE Transactions on Pattern Analysis and Machine Intelligence上,这是1篇中…

检测网络安全漏洞 工具

实验一的名称为信息收集和漏洞扫描 实验环境:VMware下的kali linux2021和Windows7 32,网络设置均为NAT,这样子两台机器就在一个网络下。攻击的机器为kali,被攻击的机器为Windows 7。 理论知识记录: 1.信息收集的步骤 2.ping命令…

PostgreSQL的学习心得和知识总结(一百六十九)|深入理解PostgreSQL数据库之 Group By 键值消除 的使用和实现

目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库…

Nacos学习(一)——基本介绍、安装与负载均衡策略

目录 一、Nacos基本介绍 二、安装与使用 (一)Nacos安装 1.上传到linux上解压 2.按需修改配置文件 3.单机启动 4.查看Nacos启动日志 5.浏览器访问Nacos服务 6.关闭Nacos服务 (二)Nacos使用 1.新建一个项目 2.最外部依赖如下 3.provider-service包的依赖 4.配置文件…

第3章 3.2 配置系统 .NET Core配置系统

3.2.1 配置系统的基本使用 .NET Core中的配置系统支持非常丰富的配置源,包括文件(JSON、XML、INI等)、注册表、环境变量、命令行、Azure Key Vault等,配置系统还支持自定义配置源。 用配置系统开发包Microsoft.Extensions.Confi…

JVM 类加载器深度解析(含实战案例)

上期文章内容:JVM类加载过程详解:从字节码到内存的蜕变之旅 目录 一、类加载器的本质是什么? 二、类加载机制全景 1.1 三阶段生命周期 1.2 关键数据结构 三、类加载器体系架构 2.1 四层标准类加载器 2.2 类加载器树形结构 四、双亲委派…

仿 Sora 之形,借物理模拟之技绘视频之彩

来自麻省理工学院、斯坦福大学、哥伦比亚大学以及康奈尔大学的研究人员携手开源了一款创新的3D交互视频模型——PhysDreamer(以下简称“PD”)。PD与OpenAI旗下的Sora相似,能够借助物理模拟技术来生成视频,这意味着PD所生成的视频蕴…

业务架构、数据架构、应用架构和技术架构

TOGAF(The Open Group Architecture Framework)是一个广泛应用的企业架构框架,旨在帮助组织高效地进行架构设计和管理。 TOGAF 的核心就是由我们熟知的四大架构领域组成:业务架构、数据架构、应用架构和技术架构。 企业数字化架构设计中的最常见要素是4A 架构。 4…

【开源免费】基于SpringBoot+Vue.JS善筹网站(JAVA毕业设计)

本文项目编号 T 205 ,文末自助获取源码 \color{red}{T205,文末自助获取源码} T205,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

vue+elementplus创建初始化安装

项目创建初始化 D:\Tool\mysql\education_vue 这个路径下cmd 或打开vscode,把项目丢进code中打开 安装element plus Container 布局容器 | Element Plus npm install element-plus --save 把项目初始文件Homeview AboutView删了,Router index.js中删一…

Word接入DeepSeek(API的作用)

1.打开”Word”,点击“文件”。 2.点击“选项”。 3.点击“信任中心”——“信任中心设置”。 4. 勾选”启用所有宏“,点击”确定“。 5.点击“自定义功能区”,勾选上“开发工具”,点击“确定”。 6.返回“文件——开发工具“下的…

Macos机器hosts文件便捷修改工具——SwitchHosts

文章目录 SwitchHosts软件下载地址操作添加方案切换方案管理方案快捷键 检测 SwitchHosts SwitchHosts 是一款 Mac 平台上的免费软件,它可以方便地管理和切换 hosts 文件,支持多种 hosts 文件格式。 软件下载地址 SwitchHosts 操作 添加方案 添加 …

Python的那些事第二十三篇:Express(Node.js)与 Python:一场跨语言的浪漫邂逅

摘要 在当今的编程世界里,Node.js 和 Python 像是两个性格迥异的超级英雄,一个以速度和灵活性著称,另一个则以强大和优雅闻名。本文将探讨如何通过 Express 框架将 Node.js 和 Python 结合起来,打造出一个高效、有趣的 Web 应用。我们将通过一系列幽默风趣的实例和表格,展…

汽车免拆诊断案例 | 2010 款路虎揽胜车空调偶尔出风异常

故障现象  一辆2010款路虎揽胜车,搭载5.0 L发动机,累计行驶里程约为16万km。车主反映,接通空调开关后,有时出风忽大忽小,有时不出风,有时要等2 min左右才出风;有时两三天出现一次,…

Django项目之订单管理part1

一.前言 我们前面把django的常用知识点给讲完了,现在我们开始项目部分,项目是一个订单管理系统,我们同时也会在项目之中也会讲一些前面没有用到的知识点。 项目大概流程如下: 核心的功能模块: 认证模块,用…

低代码与 Vue.js:技术选型与架构设计

在当下数字化转型的浪潮中,企业对应用开发的效率和质量有着极高的追求。低代码开发平台的兴起,为企业提供了一条快速构建应用的捷径,而 Vue.js 作为热门的前端框架,与低代码开发平台的结合备受关注。如何做好两者的技术选型与架构…