当前位置: 首页 > news >正文

全网都在找的Python生成器竟然在这里!简单几步,让你的代码更简洁、更高效!

在这里插入图片描述

  • 博客主页:长风清留扬-CSDN博客
  • 系列专栏:Python基础专栏
  • 每天更新大数据相关方面的技术,分享自己的实战工作经验和学习总结,尽量帮助大家解决更多问题和学习更多新知识,欢迎评论区分享自己的看法
  • 感谢大家点赞👍收藏⭐评论

在这里插入图片描述

一、生成器的定义

生成器是一种特殊的迭代器,它允许你定义一个函数,该函数会按照你的要求生成一个序列的值,但一次只返回一个值,并且在内部维护着自己的状态,以便在需要时生成下一个值。生成器是通过使用yield关键字来实现的。
推荐阅读: 来看看Python迭代器能让你的代码提升100倍的密码

二、生成器的创建

生成器可以通过以下两种方式创建:

yield关键字

函数中包含yield关键字:当一个函数中包含至少一个yield语句时,该函数就不再是一个普通函数,而是一个生成器函数。调用该函数时,会返回一个生成器对象。
在Python中,yield关键字用于在函数中创建一个生成器。生成器是一种特殊的迭代器,它允许你逐个产生值,而不是一次性返回整个序列。使用yield关键字,你可以定义一个函数,该函数在每次调用时返回一个值,并保留其状态以供下次调用时继续执行。

语法

def generator_function_name(parameters):  """  这是一个生成器函数的定义。  :param parameters: 函数的参数,可以是任意数量和类型的参数。  :yield: 在函数体中,使用yield关键字来返回一个值,并暂停函数的执行。  每次迭代生成器时,函数会从上次yield的位置继续执行。  """  # 函数体:可以包含任意数量的语句和逻辑。  # 通常会有一个循环来逐个产生值。  for item in iterable:  # iterable是一个可迭代对象,比如列表、元组、集合或字符串等。  # 可以在这里进行任何需要的计算或处理。  yield value  # 使用yield返回一个值,并暂停函数的执行。  # 这里的代码(如果有的话)不会在每次迭代时都执行,  # 除非它位于另一个循环或条件语句中。  # 注意:生成器函数通常没有return语句(或者有一个不带值的return,表示迭代结束)。  # 如果有return语句并带有值,那么在迭代结束后尝试获取下一个值时,会引发StopIteration异常,  # 并且该值会被作为StopIteration异常的value属性返回(这是Python 3.3及以后版本的行为)。

示例1

def simple_generator():  """  一个简单的生成器函数,依次返回数字0到2。  """  yield 0  yield 1  yield 2  # 使用生成器函数  
gen = simple_generator()  # 创建一个生成器对象  # 迭代生成器对象  
for value in gen:  print(value)  # 输出:0, 1, 2

在上面的示例中,simple_generator是一个生成器函数,它使用yield关键字依次返回数字0、1和2。当我们调用这个函数时,它不会立即执行完并返回结果,而是返回一个生成器对象。然后,我们可以使用for循环或其他迭代方式来逐个获取生成器产生的值。

需要注意的是,生成器函数在每次迭代时都会从上次yield的位置继续执行,直到函数结束或再次遇到yield。这意味着你可以在生成器函数中保留状态(比如循环变量、内部变量等),并在下次迭代时继续使用它们。

示例2

def fibonacci(n):  """生成斐波那契数列的前n个数"""  a, b = 0, 1  for _ in range(n):  yield a  # 返回当前的斐波那契数  a, b = b, a + b  # 更新斐波那契数列的当前数和下一个数  # 使用生成器函数  
fib_gen = fibonacci(5)  # 创建一个生成器对象  
for num in fib_gen:  # 迭代生成器对象  print(num)  # 打印每个斐波那契数

运行结果:

0  
1  
1  
2  
3

生成器表达式

  • 生成器表达式:生成器表达式类似于列表推导式,但使用圆括号而不是方括号。它们提供了一种简洁的方法来创建生成器。
  • 生成器表达式是另一种创建生成器的方式,它提供了一种简洁的语法来生成序列的值。生成器表达式使用圆括号()而不是方括号[]来定义,并且它们也使用yield关键字(尽管在表达式中这种用法是隐式的)。

语法

generator_expression = (expression for item in iterable [if condition])
  • expression:要生成的值的表达式。
  • item:从可迭代对象iterable中取出的元素。
  • iterable:要遍历的可迭代对象。
  • if condition(可选):一个条件表达式,用于过滤要生成的元素。

示例

# 创建一个生成器表达式,生成从0到9的平方数  
squares = (x**2 for x in range(10))  # 使用for循环迭代生成器表达式  
for square in squares:  print(square)

运行结果:

0  
1  
4  
9  
16  
25  
36  
49  
64  
81

生成器表达式在语法上类似于列表推导式,但它们不会一次性生成整个列表,而是返回一个生成器对象,该对象在迭代时按需生成值。这使得生成器表达式在处理大数据集时更加高效,因为它们不会占用大量内存。

总之,生成器是Python中一个非常有用的特性,它们提供了一种惰性计算的方式,只在需要时才生成值,从而节省了内存和计算资源。通过生成器函数和生成器表达式,我们可以轻松地创建和使用生成器来处理迭代逻辑和大数据集。

三、访问生成器

使用for循环遍历生成器

首先,我们定义一个简单的生成器函数:

# 定义一个生成器函数,它逐个生成从0到4的数字  
def simple_generator():  for i in range(5):  yield i  # 使用yield关键字,使函数成为一个生成器  # 使用for循环遍历生成器  
for value in simple_generator():  print(f"For loop value: {value}")

运行结果

For loop value: 0  
For loop value: 1  
For loop value: 2  
For loop value: 3  
For loop value: 4

使用__next__()方法访问生成器

生成器对象本身也有__next__()方法,可以实现与next()函数相同的功能:

# 重新创建生成器对象  
gen = simple_generator()  # 使用生成器对象的__next__()方法获取下一个值  
print(f"__next__() value: {gen.__next__()}")  # 输出第一个值  
print(f"__next__() value: {gen.__next__()}")  # 输出第二个值  
print(f"__next__() value: {gen.__next__()}")  # 输出第三个值  # 当生成器耗尽时,继续调用__next__()会引发StopIteration异常  
try:  print(f"__next__() value: {gen.__next__()}")  # 输出第四个值  print(f"__next__() value: {gen.__next__()}")  # 尝试获取第五个值,会抛出异常  
except StopIteration:  print("Generator exhausted")

输出结果:

__next__() value: 0  
__next__() value: 1  
__next__() value: 2  
__next__() value: 3  
Generator exhausted

使用next()方法访问生成器

我们可以直接使用next()函数来获取生成器的下一个值:

# 重新创建生成器对象  
gen = simple_generator()  # 使用next()方法获取生成器的下一个值  
print(f"Next value: {next(gen)}")  # 输出第一个值  
print(f"Next value: {next(gen)}")  # 输出第二个值  
print(f"Next value: {next(gen)}")  # 输出第三个值  # 当生成器耗尽时,继续调用next()会引发StopIteration异常  
try:  print(f"Next value: {next(gen)}")  # 输出第四个值  print(f"Next value: {next(gen)}")  # 尝试获取第五个值,会抛出异常  
except StopIteration:  print("Generator exhausted")

运行结果:

Next value: 0  
Next value: 1  
Next value: 2  
Next value: 3  
Generator exhausted

使用send()方法

send()方法不仅可以获取生成器的下一个值,还可以向生成器发送一个值(通过yield表达式接收)。需要注意的是,首次启动生成器不能使用send(),而必须使用next()或__next__()。

# 定义一个接受send值的生成器函数  
def generator_with_send():  received = yield "Start"  # 第一个yield,此时received是None  while True:  received = yield received  # 后续yield,将接收到的值发送回去  # 创建生成器对象  
gen = generator_with_send()  # 启动生成器  
print(f"First value: {next(gen)}")  # 必须首先使用next()启动  # 使用send()发送值并获取生成器的下一个值  
print(f"Send value: {gen.send('First send value')}")  # 发送值并获取"First send value"  
print(f"Send value: {gen.send('Second send value')}")  # 再次发送值并获取"Second send value"  # 为了避免无限循环,我们在这里停止  
# 在实际应用中,可以根据条件在生成器内部控制循环的结束

输出结果:

# 定义一个接受send值的生成器函数  
def generator_with_send():  received = yield "Start"  # 第一个yield,此时received是None  while True:  received = yield received  # 后续yield,将接收到的值发送回去  # 创建生成器对象  
gen = generator_with_send()  # 启动生成器  
print(f"First value: {next(gen)}")  # 必须首先使用next()启动  # 使用send()发送值并获取生成器的下一个值  
print(f"Send value: {gen.send('First send value')}")  # 发送值并获取"First send value"  
print(f"Send value: {gen.send('Second send value')}")  # 再次发送值并获取"Second send value"  # 为了避免无限循环,我们在这里停止  
# 在实际应用中,可以根据条件在生成器内部控制循环的结束

输出结果:

First value: Start  
Send value: First send value  
Send value: Second send value

四、yield关键字的作用

yield关键字在生成器函数中有以下几个作用:

  • 返回一个值给调用者:每次调用next()方法或迭代生成器对象时,生成器函数会从上次离开的位置继续执行,直到遇到下一个yield语句,并返回该语句的值。
  • 暂停函数执行:当生成器函数执行到yield语句时,它会暂停执行,并保存当前的所有局部变量和状态。下次调用next()方法时,它会从上次暂停的位置继续执行。
  • 记忆状态:生成器能够记住上一次迭代时的状态,这使得它能够在多次迭代中保持内部状态的一致性。

五、生成器的优势

生成器具有以下几个优势:

  • 惰性计算:生成器只在需要时才计算下一个值,这可以节省内存和计算资源。
  • 节省内存:由于生成器一次只返回一个值,并且使用迭代器协议进行迭代,因此它们可以处理大数据集而不会耗尽内存。
  • 简化代码:生成器提供了一种简洁的方法来编写迭代逻辑,使得代码更加清晰和易于维护。

六、生成器的应用场景

生成器适用于以下场景:

  • 处理大数据集:当数据集非常大时,使用生成器可以避免一次性将所有数据加载到内存中。
  • 需要惰性计算的场景:当只需要处理数据集的一部分时,生成器可以按需生成值,而无需计算整个数据集。
  • 自定义迭代逻辑:当需要自定义迭代逻辑时,生成器提供了一种灵活的方式来实现这一点。

推荐阅读

Python基础

Python全网最全基础课程笔记(一)——基础入门
Python全网最全基础课程笔记(二)——变量
Python全网最全基础课程笔记(三)——所有运算符+运算符优先级
Python全网最全基础课程笔记(四)——基本数据类型
Python全网最全基础课程笔记(五)——选择结构+Python新特性Match
Python全网最全基础课程笔记(六)——循环结构
Python全网最全基础课程笔记(七)——列表,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(八)——字典,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(九)——集合,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(十)——元组,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(十一)——字符串所有操作,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(十二)——函数,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(十三)——作用域,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!

Flink入门到就业

2024年最新Flink教程,从基础到就业,大家一起学习–基础篇
2024年最新Flink教程,从基础到就业,大家一起学习–入门篇
2024年最新Flink教程,从基础到就业,大家一起学习–Flink集群部署
2024年最新Flink教程,从基础到就业,大家一起学习–flink部署和集群部署(从本地测试到公司生产环境如何部署项目源码)
2024年最新Flink教程,从基础到就业,大家一起学习–Flink运行架构底层源码详解+实战
2024年最新Flink教程,从基础到就业,大家一起学习–Flink DataStream API-第一篇+源码讲解

在这里插入图片描述

相关文章:

全网都在找的Python生成器竟然在这里!简单几步,让你的代码更简洁、更高效!

博客主页:长风清留扬-CSDN博客系列专栏:Python基础专栏每天更新大数据相关方面的技术,分享自己的实战工作经验和学习总结,尽量帮助大家解决更多问题和学习更多新知识,欢迎评论区分享自己的看法感谢大家点赞&#x1f44…...

插入排序,希尔排序,和归并排序

每一本数据结构和算法的教科书中,都不厌其烦的介绍了排序算法。不厌其烦的介绍10余种不同的排序。那么实际编程中用得到那么多排序算法吗?当然用不到。那么为什么全世界的教科书都这么写呢?显然是醉翁之意不在酒。 数组,是每个编…...

Prompt 模版解析:诗人角色的创意引导与实践

Prompt 模版解析:诗人角色的创意引导与实践 Prompt 模版作为一种结构化工具,旨在为特定角色——本例中的“诗人”——提供明确的指导和框架。这一模版详尽地描绘了诗人的职责、擅长的诗歌形式以及创作规则,使其能在自动化系统中更加精确地执…...

zookeeper选举kafka集群的controller

zookeeper选举kafka集群的controller目录 文章目录 zookeeper选举kafka集群的controller目录前言一、实操体验controller的选举二、模拟controller选举四、删除controller节点 前言 kafka集群的controller是kafka集群中一个有特殊作用的broker,负责整个kafka集群的…...

吉如一线段树:区间最值和历史最值

区间最值和历史最值 问题一 给定一个长度为 n n n 的数组 a a a , 实现以下三种操作 : 0 l r x : 将 a r r [ l ∼ r ] arr[l\sim r] arr[l∼r] 范围的每个数 v v v , 更新为 min ⁡ ( v , x ) \min (v, x) min(v,x) 1 l r : 查询 max ⁡ i l r a r r i \max_{il}^r ar…...

数据库常见的安全特性有哪些

数据库的安全特性主要包括以下几个方面,以确保数据的机密性、完整性和可用性: 1. 身份验证(Authentication) 数据库系统会通过身份验证来确定用户的身份,常见的方式有用户名/密码验证、基于证书的验证、多因素验证&a…...

Debezium日常分享系列之:Debezium 3.0.0.Final发布

Debezium日常分享系列之:Debezium 3.0.0.Final发布 Debezium 核心的变化需要 Java 17基于Kafka 3.8 构建废弃的增量信号字段的删除每个表的详细指标 MariaDB连接器的更改版本 11.4.3 支持 MongoDB连接器的更改MongoDB sink connector MySQL连接器的改变MySQL 9MySQL…...

MVCC(多版本并发控制)

目录 1.MVCC的工作原理2.MVCC的优点3.例子 MVCC(多版本并发控制)是一种用于数据库管理系统中实现并发控制的技术。它允许多个事务同时对数据库进行读写操作,而不会相互干扰,从而提高数据库系统的性能和可用性。MVCC通过为每个事务…...

低代码可视化-uniapp响应式数据data-代码生成器

在uniapp框架中,data 是一个核心的概念,它代表了组件或uniapp实例中的响应式数据。这些数据是组件状态的基础,uniapp会根据这些数据的变化来更新DOM,从而保持视图与数据的同步。 data 的特点 响应式:uniapp使用一种称…...

10.7学习

1.安全认证 ●Session 认证中最常用的一种方式,也是最简单的。存在多节点session丢失的情况,可通过nginx粘性Cookie和Redis集中式Session存储解决 ●HTTP Basic Authentication 服务端针对请求头中base64加密的Authorization 和用户名和密码进行校验。…...

基础算法之前缀和--Java实现(下)--LeetCode题解:-和为 K 的子数组 - 和可被 K 整除的子数组 -连续数组-矩阵区域和

这里是Themberfue 和为 K 的子数组 题目解析 返回子数组中所有元素的和等于给定k的个数。 算法讲解 这题好像是用滑动窗口解决,但其实不能,因为 nums 中的元素可能存在负数,就不能保证其单调性的性质。 用前缀和求也不易想到,…...

序列化与反序列化基础及反序列化漏洞(附案例)

参考文章: [web安全原理]PHP反序列化漏洞 - 笑花大王 - 博客园 (cnblogs.com) 一、概念 为了能有效的存储数据而不丢失数据的类型和内容,经常需要通过序列化对数据进行处理,将数据进行序列化后,会生成一个字符串,字符…...

Khronos:动态环境下时空度量语义SLAM的统一方法

Khronos: A Unified Approach for Spatio-Temporal Metric-Semantic SLAM in Dynamic Environments 原文 项目 引言: 人类居住环境通常是高度动态的,人、机器人和其他实体不断移动、互动和改变场景。对于机器人在这种情况下的操作,仅仅建立一…...

一个迷茫的25岁前端程序员的自述

作者:一尾流莺 一直听说程序员的危机在 35 岁,没想到我的危机从 25 岁就开始了。 我甚至不知道自己是不是 25 岁,也可能是 26 岁,或者 27 岁,1998 年的生日,按照 2023 - 1998 的算法就是 25,按…...

多文件并发多线程MD5工具(相对快速的MD5一批文件),适配自定义MD5 Hash I/O缓存。

自己写的多文件 MD5校验工具,一个文件开一个线程,有最大I/O 缓存设置,兼容读写MD5后缀文件。 共计91个文件,合计180G左右 12分钟左右,UI基本卡废,但程序没蹦,属于正常。 卡的原因是基本是用 I/O…...

Pikachu-url重定向-不安全的url跳转

不安全的url跳转 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话就可能发生"跳错对象"的问题。 url跳转比较直接的危害是: …...

如何下载和安装CLion,图文详解

一、下载 登录JetBrains官网,下载最新版本的Clion,Clion目前没有社区版,都是专业版。 二、安装 1、启动Clion安装程序,下一步。 2、修改安装目录,下一步。 3、创建桌面快捷方式,更新PATH变量&#xff0…...

vue3导入本地图片2种实现方法

在<script setup>中使用import语法&#xff1a; <template><img :src"logo" alt"Logo"> </template><script setup> import logo from ./assets/logo.png; </script> 使用Vue的ref来动态地在<script setup>中…...

leetcode 刷题day36动态规划Part05 背包问题(完全背包、518. 零钱兑换 II、377. 组合总和 Ⅳ、70. 爬楼梯 (进阶))

完全背包 完全背包的每件商品都有无限个&#xff0c;和01背包的一不同主要体现在遍历顺序上。为了保证每个物品仅被添加一次&#xff0c;01背包内嵌的循环是从大到小遍历。而完全背包的物品是可以添加多次的&#xff0c;所以要从小到大去遍历。 518. 零钱兑换 II 思路&#…...

检查jar冲突,查找存在相同class的jar

写在前面 本文看下如何查找jar冲突&#xff0c;即查找哪些jar包中存在相同的class。如果是存在相同jar的不同版本&#xff0c;基本一眼就能看出来&#xff0c;然后结合maven的依赖关系将其剔除掉即可&#xff0c;但是当你遇到了有人手动拷贝某些class到jar包中导致冲突的情况时…...

PhpStudy-PHP5.4.45后门漏洞应用程序(C++/base64/winhttp)

PhpStudy-PHP5.4.45后门漏洞应用程序&#xff08;C/base64/winhttp&#xff09; 前言引言&#xff08;时间回到多年前&#xff09; PhpShellCmd.exe使用介绍&#xff1a;&#xff08;1&#xff09;输入网址检测是否存在PHP/5.4.45&#xff08;2&#xff09;whoami&#xff08;3…...

【优选算法】(第二十七篇)

目录 重排链表&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 合并K个升序链表&#xff08;hard&#xff09; 题目解析 讲解算法原理 编写代码 重排链表&#xff08;medium&#xff09; 题目解析 1.题目链接&#xff1a;. - 力扣&#xff08;LeetCod…...

学习Flask框架

Flask简介 Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug &#xff0c;模板引擎则使用 Jinja2 。Flask使用 BSD 授权。 Flask也被称为 “microframework” &#xff0c;因为它使用简单的核心&#xff0c;用 extension 增加其他功能。Flask没…...

Elasticsearch:使用 LLM 实现传统搜索自动化

作者&#xff1a;来自 Elastic Han Xiang Choong 这篇简短的文章是关于将结构化数据上传到 Elastic 索引&#xff0c;然后将纯英语查询转换为查询 DSL 语句&#xff0c;以使用特定过滤器和范围搜索特定条件。完整代码位于此 Github repo 中。 首先&#xff0c;运行以下命令安装…...

人脸表情行为识别系统源码分享

人脸表情行为识别系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…...

ThreadLocal原理解析及面试

基本使用 讲原理之前&#xff0c;我简单写个demo小程序说说怎么使用 public class TestThreadLocal {public static void main(String[] args) throws InterruptedException {ThreadLocal<String> tl new ThreadLocal();/**主线程设置了一个值*/tl.set("SSSSSs&…...

探索未来:mosquitto-python,AI领域的新宠

文章目录 探索未来&#xff1a;mosquitto-python&#xff0c;AI领域的新宠背景&#xff1a;为何选择mosquitto-python&#xff1f;库简介&#xff1a;mosquitto-python是什么&#xff1f;安装指南&#xff1a;如何安装mosquitto-python&#xff1f;函数用法&#xff1a;5个简单…...

C++版iwanna1

第一篇目录 开头程序Game.cpp源文件Player.h头文件Player.cpp源文件trigger.h头文件trigger.cpp源文件Cmp.h头文件Cmp.cpp源文件 开头 大家好&#xff0c;我叫这是我58。 程序 Game.cpp源文件 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <c…...

LSTM变种模型

一、GRU 1.概念 GRU&#xff08;门控循环单元&#xff0c;Gated Recurrent Unit&#xff09;是一种循环神经网络&#xff08;RNN&#xff09;的变体&#xff0c;旨在解决标准 RNN 在处理长期依赖关系时遇到的梯度消失问题。GRU 通过引入门控机制简化了 LSTM&#xff08;长短期…...

Python进阶--函数进阶

目录 1. 函数多返回值 2. 函数多种传参方式 (1). 位置参数 (2). 关键字参数 (3). 缺省参数 (4). 不定长参数 3. 匿名函数 (1). 函数作为参数传递 (2). lambda匿名函数 1. 函数多返回值 def return_num():return 1# 返回1之后就不会再向下继续执行函数体return 2 resu…...