redis中的hash

Redis中的hash是什么

Hash: 哈希,也叫散列,是一种通过哈希函数将键映射到表中位置的数据结构,哈希函数是关键,它把键转换成索引。

Redis Hash(散列表)是一种 field-value pairs(键值对)集合类型,类似于 Python 中的字典、Java 中的 HashMap。一个 field 对应一个value.

Hash冲突:两个不同的key可能会映射到同一个位置去,这种问题我们叫做哈希冲突,或者哈希碰撞
Hash冲突解决方法:主要有两种两种方法,开放定址法和链地址法。

开放定址法 :
在开放定址法中所有的元素都放到哈希表里,当一个关键字key用哈希函数计算出的位置冲突了,则按照某种规则找到一个没有存储数据
的位置进行存储。这里的规则有三种:线性探测、二次探测、双重探测。

链地址法:
开放定址法中所有的元素都放到哈希表里,链地址法中所有的数据不再直接存储在哈希表中,哈希表中存储一个指针,没有数据映射这个位置时,这个指针为空,有多个数据映射到这个位置时,我们把这些冲突的数据链接成一个链表,挂在哈希表这个位置下面,链地址法也叫做拉链法或者哈希桶。
在这里插入图片描述

Redis 的散列表 dict 由数组 + 链表构成,数组的每个元素占用的槽位叫做哈希桶,当出现散列冲突的时候就会在这个桶下挂一个链表,用“拉链法”解决散列冲突的问题。
简单地说就是将一个 key 经过散列计算均匀的映射到散列表上。
在这里插入图片描述

Hash数据类型底层存储数据结构实际上有两种。
1.dict结构。
2.在7.0版本之前使用ziplist,之后被listpack代替。

什么是listPack

Redis 在 5.0 新设计一个数据结构叫 listpack,目的是替代压缩列表,它最大特点是 listpack 中每个节点不再包含前一个节点的长度了,压缩列表每个节点正因为需要保存前一个节点的长度字段,就会有连锁更新的隐患.

listpack 也叫紧凑列表,它的特点就是用一块连续的内存空间来紧凑地保存数据,同时为了节省内存空间,listpack 列表项使用了多种编码方式,来表示不同长度的数据,这些数据包括整数和字符串。

Redis源码对于listpack的解释为 A lists of strings serialization format,一个字符串列表的序列化格式,也就是将一个字符串列表进行序列化存储。Redis listpack可用于存储字符串或者是整型

为了避免 ziplist 引起的连锁更新问题,listpack 中的每个列表项不再像 ziplist 列表项那样,保存其前一个列表项的长度,它只会包含三个方面内容,分别是当前元素的编码类型(entry-encoding)、元素数据 (entry-data),以及编码类型和元素数据这两部分的长度 (entry-len),如下图所示。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • slen,不同于ziplist,listpackEntry 中的 len 记录的是当前 entry 的编码类型和长度,而非上一个entry的长度。
  • *sval,当存储的数据为字符串时,使用该成员变量
  • lval,当存储的数据为整数,使用该成员变量
    通常情况下使用dict数据结构存储数据,每个field-va1 ue pairs构成一个dictEntry节点来保存。

只有同时满足以下两个条件的时候,才会使用listpack(7.O版本之前使用ziplist)数据结构来代替dict存储,把key-value键值对按照
field在前value在后,紧密相连的方式放到一次把每个键值对放到列表的表尾。

  • ·每个键值对中的field和value的字符串字节大小都小于hash-max-listpack-value配置的值(默认64)。
  • ·field-value pairs键值对数量小于hash-max-listpack-entries配置的值(默认512)。

每次向散列表写数据的时候,都会调用t_hash.c中的hashTypeConvertListpack()函数来判断是否需要转换底层数据结构。

当插入和修改的数据不满足以上两个条件时,就把散列表底层存储结构转换成dict结构。需要注意的是,不能由dict退化成listpack。

虽然使用了listpack就无法实现O(1)时间复杂度操作数据,但是使用listpack能大大减少内存占用,而且数据量比较,小,性能并不是有太大差异。

Redis数据库就是一个全局散列表。正常情况下,我只会使用ht_table[0]散列表,图2-20是一个没有进行rehash状态下的字典。
在这里插入图片描述

dict字典在源代码dict.h中使用dict结构体表示。
在这里插入图片描述

1.dictType *type

  • 这是一个指向 dictType 结构的指针,dictType 通常定义了哈希表的操作接口,包括哈希函数、键值的比较函数、释放键值的函数等。这使得哈希表可以针对不同的数据类型进行定制化操作。

2.dictEntry **ht_table[2]

  • 这是一个包含两个指针的数组,每个指针指向一个哈希表(ht_table[0] 和 ht_table[1])。这种设计是为了支持渐进式重新哈希(Incremental Rehashing)。当哈希表的负载因子(即 ht_used[0] / ht_table[0] 的大小)超过某个阈值时,Redis 会开始将数据从 ht_table[0] 重新哈希到 ht_table[1]。这种渐进式重新哈希可以避免一次性重新哈希带来的性能问题。
  • dictEntry是哈希表中存储键值对的结构,通常包含键、值和指向下一个哈希冲突的指针。

3.unsigned long ht_used[2]

  • 这是一个包含两个元素的数组,分别记录 ht_table[0] 和 ht_table[1] 中存储的键值对数量。ht_used[0] 表示 ht_table[0] 中的元素数量,ht_used[1] 表示 ht_table[1] 中的元素数量。

4.long rehashidx

  • 这是一个索引值,用于记录当前重新哈希操作的进度。当哈希表正在进行重新哈希时,rehashidx 表示当前正在处理的桶索引。如果 rehashidx 为 -1,表示没有正在进行的重新哈希操作。

5.int16_t pauserehash

  • 这是一个标志位,用于控制重新哈希操作是否暂停。在某些情况下,Redis 可能需要暂停重新哈希操作,以避免对性能的影响。例如,当 Redis 正在执行 RDB(Redis Database Backup)操作时,可能会暂停重新哈希。

6.signed char ht_size_exp[2]

  • 这是一个包含两个元素的数组,分别记录 ht_table[0] 和 ht_table[1] 的大小指数。Redis 的哈希表大小通常是 2 的幂次方,ht_size_exp[0] 和 ht_size_exp[1] 分别表示 ht_table[0] 和 ht_table[1] 的大小指数。例如,如果 ht_size_exp[0] 为 4,则 ht_table[0] 的大小为 24=16。
    在这里插入图片描述

·*key指针指向键值对中的键,实际上指向一个SDS实例。
虽然Redis是用c实现的,但是他们的string结构并不相同,Redis中的字符串是可以修改的字符串,在内存中它是以字节数组的形式存在的Redis 的。字符串叫sds,也就是 Simple Dynamic String,是一个带长度信息的字节数组
在这里插入图片描述

·v是一个uon联合体,表示键值对中的值,同一时刻只有一个字段有值,用联合体的目是节省内存。

  • ·val 如果值是非数字类型,那就使用这个指针存储。
  • ·uint64tu64, 值是无符号整数的时候使用这个字段存储。
  • ·int64ts64, 值是有符号整数时,使用该字段存储。
  • ·dob1ed, 值是浮点数是,使用该字段存储。
    *next指向下一个节点指针,当散列表数据增加,可能会出现不同的key得到的哈希值相等,也就是说多个key对应在一个哈希桶里面,这就是哈希冲突。Redis使用拉链法,也就是用链表将数据串起来。

为什么说v是一个uo联合体,表示键值对中的值,同一时刻只有一个字段有值,用联合体的目是节省内存?

1.节省内存

  • union 联合体是一种特殊的数据结构,它允许在同一个内存位置存储不同的数据类型。所有成员共享同一块内存,因此在任何时刻,union 中只有一个成员有值。写入一个成员会覆盖其他成员的内容.
  • 在 dictEntry 中,v 的大小由其最大的成员决定。例如,void *val、uint64_t u64、int64_t s64 和 double d 的大小都是 8 字节(在 64 位系统中)。因此,v 的大小也是 8 字节,无论存储哪种类型的数据,都不会占用额外的内存。

2.灵活存储不同类型的数据

  • Redis 的哈希表需要存储多种类型的数据,包括指针、整数和浮点数。通过使用 union,v 可以灵活地存储这些不同类型的数据,而不需要为每种类型分配单独的内存空间。
  • 这种设计使得 dictEntry 能够高效地处理不同类型的数据,同时保持内存占用的最小化。

为啥ht_table[2]存放了两个指向散列表的指针?用一个散列表不就够了吗?

默认使用ht_tab:1e[0]进行读写数据,当散列表的数据越来越多的时候,哈希冲突严重会出现哈希桶的链表比较长,导致查询性能下降。

为了唯快不破想了一个法子,当散列表保存的键值对太多或者太少的时候,需要通过「rehash(重新散列)对散列表进行扩容或者缩容。

扩容和缩容

1.为了高性能,减少哈希冲突,会创建一个大小等于ht_used[0]*2的散列表ht_tab1e[1],也就是每次扩容时根据散列表ht_tab1e[0]已使用空间扩大一倍创建一个新散列表ht_tab1e[1]。反之,如果是缩容操作,就根据ht_tab1e[0]已使用空间缩小一倍创建一个新的散列表。

2.重新计算键值对的哈希值,得到这个键值对在新散列表ht_tab1e[1]的桶位置,将键值对迁移到新的散列表上。

3.所有键值对迁移完成后,修改指针,释放空间。具体是把ht_tab1e[0]指针指向扩容后的散列表,回收原来小的散列表内存空间,ht_tab1e[1]指针指向NULL,为下次扩容或者缩容做准备。

什么时候会触发扩容?

1.当前没有执行BGSAVE或者BGREWRITEAOF命令,同时负载因子大于等于1。也就是当前没有RDB子进程和AOF重写子进程在工作,毕竞这俩操作还是比较容易对性能造成影响的,就不扩容火上浇油了。

2.正在执行BGSAVE或者BGREWRITEA0F命令,负载因子大于等于5。(这时候哈希冲突太严重了,再不触发扩容,查询效率太慢了)。负载因子=散列表存储dictEntry节点数量/散列表桶个数。完美情况下,每个哈希桶存储一个dictEntry节点,这时候负载因子=1。

BGSAVE 和 BGREWRITEAOF 是 Redis 中的两个重要命令,它们分别用于实现 Redis 的两种持久化机制:RDB(Redis Database Backup) 和 AOF(Append Only File)。这两种机制用于将内存中的数据持久化到磁盘,以防止数据丢失。

BGREWRITEAOF 命令触发一个后台进程(子进程)来重写 AOF 文件,以压缩和优化 AOF 文件的大小,同时避免阻塞主进程。

需要迁移数据量很大,rehash操作岂不是会长时间阻塞主线程?

为了防止阻塞主线程造成性能问题,我并不是一次性把全部的key迁移,而是分多次,将迁移操作分散到每次情求中,避免集中式rehash造成长时间阻塞,这个方式叫渐进式rehash。

在执行渐进式rehash期间,dict会同时使用ht_table[0]和ht_table[1]两个散列表,rehash具体步如下:

1.将rehashidxi设置成0,表示rehash开始执行。

2.在rehash期间,服务端每次处理客户端对dict散列表执行添加、查找、删除或者更新操作时,除了执行指定操作以外,还会检查当前dict是否处于rehash状态,是的话就把散列表ht_table[0]上索引位置为rehashidx的桶的链表的所有键值对rehash到散列表ht_table[1]上,这个哈希桶的数据迁移完成,就把rehashidx的值加1,表示下一次要迁移的桶所在位置。

3.当所有的键值对迁移完成后,将rehashidxi设置成-1,表示rehash操作已完成。

rehash过程中,字典的删除、查找、更新和添加操作,要从两个ht_table都搞一遍吗?

删除、修改和查找可能会在两个散列表进行,第一个散列表没找到就到第二个散列表进行查找。但是增加操作只会在新的散列表上进行。

如果请求比较少,岂不是会很长时间都要使用两个散列表?

在Redis Server园初始化时,会注册一个时间事件,定时执行serverCron函数,其中包含rehash操作用于辅助迁移,避免这个问题。
serverCron函数除了做rehash以外,主要处理如下工作。

  • 过期key删除。
  • 监控服务运行状态。
  • 更新统计数据。
  • 渐进式rehash。
  • 触发BGSAVE/AOF rewrite以及停止子进程。
  • 处理客户端超时。

扩容过程:

在 Redis 的哈希表(Hash)rehash 过程中,数据迁移是分步骤、渐进式进行的,这样做是为了避免一次性迁移大量数据造成的服务器阻塞。以下是 rehash 过程中数据迁移的具体步骤:
1. 创建新的哈希表
当触发 rehash 条件时(例如,负载因子超过设定阈值),Redis 会创建一个新的哈希表 ht[1],其大小通常是 ht[0](当前哈希表)大小的两倍。

2. 初始化 rehash 索引
在 dict 结构中,rehashidx 被初始化为 0。这个索引用于跟踪 rehash 过程中已经迁移的桶的数量。

3. 渐进式迁移
Redis 使用一个定时任务或者在处理命令时的空闲时间来执行 rehash 操作。在每次 rehash 操作中,会迁移一定数量的桶(通常是一个或几个),而不是一次性迁移所有桶。具体步骤如下:

  • 从 ht[0] 中取出一个桶(通过 rehashidx 定位)。
  • 遍历桶中的所有 dictEntry(如果有链表,则遍历链表中的所有条目)。
  • 重新计算每个 dictEntry 的哈希值,并将其插入到 ht[1] 中对应的桶中。
  • 更新 rehashidx,指向下一个需要迁移的桶。

4. 更新 rehash 状态
每次迁移一定数量的桶后,Redis 会更新 rehashidx,使其指向下一个桶。这样,下一次 rehash 操作可以从上次停止的地方继续。

5. 完成 rehash
当 rehashidx 超过 ht[0] 的大小时,表示所有桶都已迁移到 ht[1]。此时,Redis 会进行以下操作:

  • 将 ht[1] 设置为新的 ht[0],即让新的哈希表成为当前使用的哈希表。
  • 释放旧的 ht[0] 占用的内存。
  • 将 rehashidx 重置为 -1,表示 rehash 操作已完成。

6. 处理命令时的 rehash
在 rehash 过程中,Redis 仍然可以处理客户端的命令。当命令涉及到哈希表操作时,Redis 会同时在 ht[0] 和 ht[1] 中查找或插入数据,确保数据的一致性。
通过这种渐进式的 rehash 机制,Redis 能够在不影响服务器性能的情况下,平滑地完成哈希表的扩容操作。

BGSAVE和BGREWRITEAOF是什么意思?

BGSAVE 和 BGREWRITEAOF 是 Redis 中的两个重要命令,它们分别用于实现 Redis 的两种持久化机制:RDB(Redis Database Backup) 和 AOF(Append Only File)。这两种机制用于将内存中的数据持久化到磁盘,以防止数据丢失。
1. BGSAVE(RDB 持久化)
RDB 持久化

  • 定义:RDB 是一种快照持久化机制,它会定期将内存中的数据集快照保存到磁盘上的一个 RDB 文件中。

  • 优点:

    • 数据恢复速度快:RDB 文件是一个紧凑的二进制文件,恢复数据时速度较快。
    • 适合全量备份:适合用于全量数据备份,可以方便地将数据备份到其他存储介质或远程服务器。
  • 缺点:

  • 数据丢失风险:如果 Redis 服务器在两次快照之间发生故障,可能会丢失最后一次快照之后的数据。

  • 阻塞风险:生成 RDB 文件的过程可能会阻塞主进程,尤其是在数据量较大时。

BGSAVE 命令

  • 作用:触发一个后台进程(子进程)来生成 RDB 文件,而主进程继续处理客户端请求,避免阻塞。

  • 执行过程:

    a.主进程创建一个子进程。
    b.子进程将当前内存中的数据集快照写入到一个新的 RDB 文件中。
    c.子进程完成写入后,用新生成的 RDB 文件替换旧的 RDB 文件。

  • 触发方式:

    • 手动触发:可以通过命令 BGSAVE 手动触发。
    • 自动触发:Redis 会根据配置的策略自动触发 BGSAVE。例如,可以配置 Redis 每隔一定时间或在数据变更达到一定数量时自动执行 BGSAVE。

2. BGREWRITEAOF(AOF 持久化)
AOF 持久化

  • 定义:AOF 是一种日志持久化机制,它会将每个写操作命令追加到一个日志文件(AOF 文件)中。
  • 优点:
    • 数据安全性高:AOF 文件记录了每个写操作,即使 Redis 服务器发生故障,也可以通过重放 AOF 文件中的命令恢复数据。
    • 可配置性强:可以配置不同的同步策略(如每秒同步一次、每次写操作同步一次等),以平衡性能和数据安全性。
  • 缺点:
    • 文件体积大:AOF 文件会不断增长,可能会占用大量磁盘空间。
    • 恢复速度慢:AOF 文件是文本格式,恢复数据时速度相对较慢。

BGREWRITEAOF 命令

  • 作用:触发一个后台进程(子进程)来重写 AOF 文件,以压缩和优化 AOF 文件的大小,同时避免阻塞主进程。

  • 执行过程:

    a.主进程创建一个子进程。
    b.子进程读取当前内存中的数据集,并将其转换为一系列优化后的写操作命令,写入到一个新的 AOF 文件中。
    c.子进程完成写入后,用新生成的 AOF 文件替换旧的 AOF 文件。

  • 触发方式:

    • 手动触发:可以通过命令 BGREWRITEAOF 手动触发。
    • 自动触发:Redis 会根据配置的策略自动触发 BGREWRITEAOF。例如,可以配置 Redis 在 AOF 文件大小达到一定比例时自动执行 BGREWRITEAOF。

总结

  • BGSAVE:用于生成 RDB 文件,适合全量数据备份,恢复速度快,但可能会丢失最后一次快照之后的数据。
  • BGREWRITEAOF:用于重写 AOF 文件,优化 AOF 文件的大小,数据安全性高,但文件体积大,恢复速度相对较慢。
    这两种持久化机制可以单独使用,也可以结合使用,具体选择取决于应用场景和对数据安全性的要求。

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

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

相关文章

弹簧质点系统(C++实现)

本文实现一个简单的物理算法:弹簧质点系统(Mass-Spring System)。这是一个经典的物理模拟算法,常用于模拟弹性物体(如布料、弹簧等)的行为。我们将使用C来实现这个算法,并结合链表数据结构来管理…

领域大模型

领域技术标准文档或领域相关数据是领域模型Continue PreTrain的关键。 现有大模型在预训练过程中都会加入书籍、论文等数据,那么在领域预训练时这两种数据其实也是必不可少的,主要是因为这些数据的数据质量较高、领域强相关、知识覆盖率(密度…

Wincc项目被锁定无法打开

Wincc项目被锁定无法打开 解决方法 解决方法 一般这种情况是因为项目打开的时候直接关机导致的。 删除项目文件夹的ProjectOpened.lck的文件夹即可 然后即可正常打开项目

SpringBoot3笔记

简介: springboot整合了springframework,整合了许多配置,让我们能够快速创建一个以springframework为基础的项目。 问题: 到目前为止,你已经学习了多种配置Spring程序的方式。但是无论使用XML、注解、Java配置类还是…

DeepSeek和文心一言的区别

文章目录 1.开发公司:2.应用场景:3.训练数据:4.模型架构:5.技术特点:6.语言风格:7.开源性:8.界面与用户体验: 1.开发公司: DeepSeek 由杭州深度求索人工智能基础技术研究…

Windows 10 安装Mysql 8

安装准备 下载 MySQL Windows ZIP版(无安装程序): 进入官网:https://dev.mysql.com/downloads/mysql/ 选择 Windows → 下载 ZIP Archive,例如: mysql-8.0.34-winx64.zip 如果你的电脑没有安装 VC Redi…

ARM分拣机vs传统PLC:实测数据揭示的4倍效率差

在苏州某新能源汽车零部件仓库,凌晨3点的分拣线上依然灯火通明。8台搭载ARM Cortex-A72处理器的智能分拣机正在以每秒3件的速度处理着形状各异的电池包组件,它们通过MES系统接收订单信息,自主规划最优路径,将不同规格的零部件精准…

使用python访问mindie部署的vl多模态模型

说明 今天使用mindie1.0部署了qwen2_7b_vl模型,测试过程出现一些问题,这里总结下。 问题1:transformers版本太低 报错信息: [ERROR] [model_deploy_config.cpp:159] Failed to get vocab size from tokenizer wrapper with ex…

vscode 跳转失败之c_cpp_properties.json解析

{"configurations": [{"name": "Linux", // 配置名称,对应当前平台,VS Code 中可选"includePath": ["${workspaceFolder}/**", // 包含当前工作区下所有文件夹的头文件(递归&…

飞速(FS)解决方案验证实验室搬迁升级,赋能客户技术服务

飞速(FS)解决方案验证实验室近日顺利完成搬迁升级,标志着飞速(FS)在解决方案可行性验证、质量保障以及定制化需求支持方面迈上新台阶,进一步提升了产品竞争力和客户信任度。 全新升级的实验室定位为技术验证…

安装kerberos认证的cdh环境

1、服务端安装 1.1 安装wget yum -y install wget 由于本地已安装过wget,所以显示Nothing to do 1.2 进入 home 目录 cd /home 1.3 下载centos6.7.iso文件,并挂载 wget https://archive.kernel.org/centos-vault/6.7/isos/x86_64/CentOS-6.7-x86_64…

MySQL基础 [六] - 内置函数+复合查询+表的内连和外连

内置函数一般要用select调用 内置函数 日期函数 current_date函数 current_date函数用于获取当前的日期。如下: current_time函数 current_time函数用于获取当前的时间。如下: now函数 now函数用于获取当前的日期时间。如下: date函数 dat…

CS内网渗透 - 如何通过冰蝎 Webshell 上线 Weblogic 服务器到 Cobalt Strike 并绕过杀软检测(360、火绒)?

目录 1. 冰蝎连接上 Weblogic 服务器如何上线到 Cobalt Strike 2. 服务器安装杀毒工具如何绕过杀软上线到 Cobalt Strike 2.1 杀软对 Webshell 命令执行的检测及绕过 2.2 杀软对 Cobalt Strike 上线木马的检测及绕过 2.3 杀软对这两方面的限制及综合绕过 3. 如何生成免杀…

[ctfshow web入门] web10

前置知识 cookie Cookie是网站存储在浏览器中的小数据片段,用于识别用户、保持登录状态或记住偏好设置。 也就是说,我以会员A的身份登录了网站,网站会发送一段cookie(会员卡)给我,上面写着会员卡A,下一次我再访问&am…

蓝桥杯:日期统计

文章目录 问题描述解法一递归解法二:暴力破解 问题描述 首先我们要了解什么是子序列,就是一个序列之中可以忽略元素但是不能改变顺序之后获得的序列就叫做子序列。 如"123"就是"11234"的子序列而不是"11324"的子序列 解法…

蓝桥杯 C/C++ 组历届真题合集速刷(一)

一、1.单词分析 - 蓝桥云课 &#xff08;模拟、枚举&#xff09;算法代码&#xff1a; #include <bits/stdc.h> using namespace std;int main() {string s;cin>>s;unordered_map<char,int> mp;for(auto ch:s){mp[ch];}char result_charz;int max_count0;fo…

重塑知识的引擎:人工智能如何改变知识的生产与传播

一、引言&#xff1a;知识的边界正在被人工智能重构 千百年来&#xff0c;人类对于“知识”的获取方式一直遵循着某种路径依赖&#xff1a;感知现实 → 归纳总结 → 文字表达 → 教育传承 → 学术沉淀。这一过程复杂而缓慢&#xff0c;需要经过代际的努力才能实现知识的积累与…

list的底层:

我们之前讲解了list&#xff0c;今天我们来看一下list的底层&#xff1a; list底层是一个双向带头循环的链表&#xff0c;之前我们学习数据结构的时候&#xff0c;我们就学过。 迭代器的封装&#xff1a; 我们看这个图片&#xff0c;我们的链表的指针可以达到链表的迭代器能力…

遵循IEC62304YY/T0664:确保医疗器械软件生命周期合规性

一、EC 62304与YY/T 0664的核心定位与关系 IEC 62304&#xff08;IEC 62304&#xff09;是国际通用的医疗器械软件生命周期管理标准&#xff0c;适用于所有包含软件的医疗器械&#xff08;如嵌入式软件、独立软件、移动应用等&#xff09;&#xff0c;其核心目标是确保软件的安…

【next函数python】`next()`函数

在Python中&#xff0c;next()函数结合生成器表达式用于高效地查找序列中第一个符合条件的元素。以下是如何理解和编写类似代码的步骤&#xff1a; 1. 生成器表达式 生成器表达式&#xff08;如 (e for e in energy3 if e ! 0)&#xff09;是一种惰性计算的迭代结构。它不会一…