Python | Iter/genartor | 一文了解迭代器、生成器的含义\区别\优缺点

前提

一种技术的出现,需要考虑:

  1. 为了实现什么样的需求;
  2. 遇到了什么样的问题;
  3. 采用了什么样的方案;
  4. 最终接近或达到了预期的效果。

概念

提前理解几个概念:

  1. 迭代

    我们经常听到产品迭代、技术迭代、功能迭代,这里的迭代的意思是在现有产品、技术、功能等基础上进行研发升级的过程,就可以理解为迭代。

    从编程的角度讲,迭代是指重复执行一组操作的过程,通常是通过循环来实现。在编程中,迭代是遍历数据集合的一种方式,允许逐个访问集合中的元素。

  2. 可迭代

    可迭代是指能够被迭代的对象,即可以通过迭代遍历其元素的对象。Python中的可迭代对象可以是列表、元组、字典、字符串等。可迭代对象支持使用for循环进行迭代。

  3. 可迭代对象

    可迭代对象是实现了迭代协议的对象,即具有__iter__()方法的对象。该方法返回一个迭代器对象。

  4. 迭代器

    迭代器是一个具有__iter__()__next__()方法的对象,实现了迭代协议。__iter__()方法返回迭代器对象本身,而__next__()方法返回下一个元素。当没有元素可以迭代时,__next__()应该引发StopIteration异常。

    例如,可以使用内置的iter()函数将可迭代对象转换为迭代器。当使用next()函数从迭代器中获取下一个元素时,如果没有元素可供迭代,将引发StopIteration异常。

  5. 生成器

    生成器是一种特殊类型的迭代器,使用函数来生成值,而不是一次性构建并存储在内存中,所以极大减少内存使用。

    生成器函数使用yield语句产生值,而不是return。每次调用生成器的__next__()方法时,生成器函数会从上次yield语句的位置恢复执行,并继续执行直到遇到下一个yield语句或函数结束。

    这样可以有效地处理大量数据,因为它们允许逐个生成值,而不需要一次性生成整个序列。

普通实现

假设为了实现获取斐波那契数列的前多少位数据,一般采用的方式肯定是通过函数计算,将函数的计算值一次一次的返回并存储在一个如列表的容器中,然后再将容器数据遍历循环处理,代码示例如下:

def func(p_max):def get_data(a, b):return a + ba, b, count = 0, 1, 0p_lst = []while count < p_max:value = get_data(a, b)a, b, count = b, value, count + 1p_lst.append(value)return p_lst
return_values = func(1000000000)
print(return_values)
for i in return_values:# do somethingpass

当p_max不大时,p_lst存储的数据不多,消耗的内存不大;一旦p_max比较大时,比如100,000,000时,p_lst存储内容就太多了,使用的内存也就会变得极大,甚至撑爆。
我们可以看一下当p_max设置为100,000,000时,30s内存就上限了。
在这里插入图片描述
这只是一个方法的使用,在开发系统时,如果存在这样的操作,系统说不定在什么时候就因为内存问题被撑爆了,这是很可怕的。

进一步优化

为了避免这样的内存爆炸问题,最好的方式就是不存储所有结果,计算出一个就消费一个,方法每次只返回一个值,然后将其他变量覆盖重用循环往复,这样不就不会存在内存问题了。

def get_data(a, b):return a + b
p_max = 1000000000
a, b, count = 0, 1, 0
while count < p_max:value = get_data(a,b)# do something use valueprint(value)

在这里插入图片描述

经过等待,发现内存并没有多少变化,说明确实有效果。

但从上面看出,这里的循环使用while进行判断操作,和我们通常使用的遍历方法用法不同,那么是否可以将上述方法采用遍历的形式计算产生并消费呢?迭代器

迭代器

首先我们自行创建一个,实现__iter__()__next__()方法:

class MyFb:def __init__(self, a, b, compute_time):# 斐波那契左数self.a = a# 斐波那契右数self.b = b# 计算多少次几次斐波那契值self.compute_time = compute_time# 初始化计次器self.current_time = 0def __iter__(self):return selfdef __next__(self):# 当计次器值 小于 总计算次数时,计算斐波那契数列值并将a、b向后推移if self.current_time < self.compute_time:value = self.a + self.bself.a = self.bself.b = valueself.current_time += 1#print("%s/%s - %s" % (self.current_time,self.compute_time,value))return valueelse:raise StopIteration# 斐波那契起始值0、1,共计次10次
myfb = MyFb(0, 1, 1000000000)
for i in myfb:# do somethingprint(i)# while myfb:
#     try:
#         next(myfb)
#     except StopIteration as e:
#         print('End!')
#         break
# 斐波那契起始值0、1,共计次10次

我们已经可以对通过MyFB类创建的myfb迭代器对象进行逐一遍历获取、访问、处理;

但是,为了能使对象被遍历,需要创建一个类并手动进行内置函数__iter__()__next__()的定制,不仅徒增了代码量,也降低了代码的可读性。

有没有什么简单的方法就能实现迭代器的功能,还能保持代码易操作、易读的方式? 生成器

生成器

生成器(Generator)实际上是迭代器的一种特殊类型。(生成器只是一种便捷实现迭代器的方式而已)

通过使用函数yield 语句创建迭代器(每次执行完后会将global(), local() 环境变量缓存起来,下次执行时从yield处开始并恢复global(), local() 环境变量),每次遍历时,执行到yield时就将 yield后的结果返回回来,生成器函数并不使用return。

生成器具有迭代器的所有特性,并且还有一些额外的优势。

为了明显的说明其原理,我们写一个比较简单理解但是并不美观的代码:

def fun(p_max):a = 0b = 1count = 0while count < p_max:value = a + byield valuea = bb = valuecount += 1g_values = fun(100000000)
print(g_values)
while True:try:p_value = next(g_values)print(p_value)except StopIteration:print('END!')break

在这里插入图片描述

因为for兼容了迭代器的异常处理,所以我们可以直接使用:

def fun(p_max):a = 0b = 1count = 0while count < p_max:value = a + byield valuea = bb = valuecount += 1g_values = fun(10000000000)
print(g_values)
for i in g_values:print(i)

继续简化代码可以写为:

def fun(p_max):a,b,count = 0,1,0while count < p_max:yield a+ba,b,count = b,a+b,count+1for i in fun(10000000000):print(i)

所以,迭代器是一种访问数据的方式,生成器是一种更加便捷实现的形式,而它们最主要的优点就是延迟数据生成,减少内存消耗,不要将其想的太复杂,只是一种措施、一种手段而已。

优缺点

生成器原本即为迭代器的特殊模式,所以可以看一下对于迭代器而言的优缺点都有哪些。

优点

  1. 内存效率: 迭代器按需生成元素,一次只产生一个元素,因此在处理大规模数据集时,迭代器能够更好地节省内存。这对于在有限内存环境中处理大型数据集或流式数据非常有利。
  2. 惰性计算: 迭代器支持惰性计算,只在需要时生成元素。这使得它们适用于处理无限序列或大规模数据,因为不需要一次性生成整个序列。
  3. 适用于多次迭代: 一旦迭代器耗尽了所有元素,可以通过重新调用 __iter__() 方法将其重新初始化,使得可以再次从头开始迭代。这使得迭代器适用于需要多次迭代相同数据集的情况。
  4. 支持 for 循环: 迭代器实现了迭代协议,因此可以直接用于 for 循环中。这样的代码更加简洁和易读。
  5. 支持无限序列: 由于迭代器是按需生成元素的,它们可以用于表示无限序列。这在模拟无限数据流等场景中非常有用。
  6. 支持并发操作: 由于迭代器是逐个产生元素的,它们可以在多线程或多进程环境中更容易地被共享和处理,而不需要担心整个数据集的同步问题。

缺点

  1. 不支持随机访问: 迭代器一次只能产生一个元素,无法通过索引直接访问元素。如果需要通过索引或其他方式随机访问数据集的元素,迭代器可能不是最佳选择。
  2. 代码繁琐: 相对于直接使用列表等数据结构,实现迭代器可能需要编写更多的代码,包括实现 __iter__()__next__() 方法。这可能在某些情况下增加了代码的复杂性。
  3. 不适用于所有场景: 尽管迭代器在许多情况下非常有用,但并不是所有问题都适合使用迭代器。在某些场景下,传统的数据结构和方法可能更加直观和简单。
  4. 一次性消耗: 大多数迭代器是一次性的,即一旦迭代器耗尽了所有元素,就不能重新开始。这与一些需要多次迭代相同的场景不匹配。
  5. 不易调试: 由于迭代器是按需生成元素的,当程序发生错误时,调试可能变得更加困难。在某些情况下,你可能无法直接查看整个数据集,而需要通过逐步迭代来定位问题。
  6. 不支持修改: 大多数迭代器是只读的,不支持在迭代过程中修改数据集。如果需要修改数据集,可能需要使用其他数据结构。





🎉如果对你有所帮助,可以点赞、关注、收藏起来,不然下次就找不到了🎉


【点赞】⭐️⭐️⭐️⭐️⭐️
【关注】⭐️⭐️⭐️⭐️⭐️
【收藏】⭐️⭐️⭐️⭐️⭐️

Thanks for watching.
Kenny

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

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

相关文章

零基础学习数学建模——(二)数学建模的步骤

本篇博客将详细介绍数学建模的步骤。 文章目录 引例&#xff1a;年夜饭的准备第一步&#xff1a;模型准备第二步&#xff1a;模型假设第三步&#xff1a;模型建立第四步&#xff1a;模型求解第五步&#xff1a;结果分析第六步&#xff1a;模型检验第七步&#xff1a;模型应用及…

openeuler的安装和两台linux主机配置ssh实现互相免密登陆

一、openeuler的安装 下载OpenEuler - 网址&#xff1a;https://www.openeuler.org/zh/download/archive/ - 版本选择&#xff1a;openEuler 22.03 LTS SP2 &#xff08;镜像文件&#xff09; &#xff0c;即长期更新版 设置自定义硬件 内存&#xff1a;推荐2GB 处理器&…

oracle基本用户管理和权限分配

1.用户与模式的关系&#xff0c;一一对应的关系 2.创建与管理用户 2.1创建用户语法 CREATE user wdf IDENTIFIED by tiger--创建用户wdf,密码tiger DEFAULT tablespace users--用户的默认表空间 quota 10M on users;--在表空间的占用最大空间 注意&#xff1a;用户创建以后…

rke2 Offline Deploy Rancher v2.8.0 latest (helm 离线部署 rancher v2.8.0)

文章目录 预备条件为什么是三个节点&#xff1f;​预备条件配置私有仓库介质清单安装 helm安装 cert-manager下载介质镜像入库helm 部署卸载 安装 rancher镜像入库helm 安装 验证 预备条件 所有支持的操作系统都使用 64-bit x86 架构。Rancher 兼容当前所有的主流 Linux 发行版…

如何通过兴趣爱好选职业?

一个错误的选择&#xff0c;可能造成终身的遗憾&#xff0c;一个正确的选择&#xff0c;可以让我们少奋斗几十年。所以无论现在付出多少代价&#xff0c;多花一些时间&#xff0c;去研究以下未来的职业方向&#xff0c;这是值得的。 职业定位&#xff08;专业定位&#xff09;…

深兰科技AI医疗健康产品获3000台采购订单

12月6日&#xff0c;武汉某企业与深兰科技签署协议&#xff0c;一次性采购3000台深兰科技AI生理健康检测仪——扁鹊。 深兰科技AI生理健康检测仪——扁鹊是深兰科技推出的人体生理指标检测产品。基于AI生物技术、融合互联网医疗及AIoT技术&#xff0c;深兰科技AI生理健康检测仪…

YOLOv8-Seg改进:轻量化改进 | 华为Ghostnet,超越谷歌MobileNet | CVPR2020

🚀🚀🚀本文改进: Ghost bottleneck为堆叠Ghost模块 ,与YOLOV8建立轻量C2f_GhostBottleneck 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何训练YOLOv8-seg; 2)模型创新,提…

HubSpot CRM:卓越客户服务的关键引擎

在数字化时代&#xff0c;提供卓越的客户服务是企业成功的关键之一。HubSpot CRM以其强大的功能和灵活性&#xff0c;成为实现卓越客户服务的关键引擎&#xff0c;以下是强调HubSpot CRM在客户服务中的应用的关键方面&#xff1a; 1. 全面的客户视图 HubSpot CRM集成了全面的…

《路由与交换技术》---练习题(无答案纯享版)

注意&#xff01;&#xff01;&#xff01;这篇blog是无答案纯享版的 选择填空的答案我会放评论区 简答题可以看这里 计算题可以发私信问我&#xff08;当然WeChat也成&#xff09;but回讯息很慢 一、选择题 1.以下不会在路由表里出现的是: ( ) A.下一跳地址 B.网络地址 C…

科大讯飞星火大模型加持数字员工系列产品发布

面对时代浪潮&#xff0c;基业长青的企业总会率先拥抱变化&#xff0c;在时代交替中创造新的增长空间。当数字化浪潮涌入千行百业&#xff0c;企业掌舵者如何选择转型&#xff1f; 从数字员工到灯塔工厂&#xff0c;愈发成熟的人工智能技术已深入企业管理&#xff0c;持续提高…

小白苦恼:电脑那么多USB口,怎么知道哪个读写更快?

前言 最近有个朋友和小白抱怨&#xff1a;电脑那么多USB接口&#xff0c;有些接口在传输文件的时候实在慢的很。 电脑诞生以来&#xff0c;USB接口就一直存在。但是USB接口还是长得几乎一样&#xff0c;不仔细去研究都不知道哪个USB会更快。 许多小伙伴就会直接放弃辨认&…

计算机导论03-计算机组成

计算机系统结构 冯•诺依曼体系结构 冯•诺依曼体系结构的基本要点 冯•诺依曼思想即冯•诺依曼体系结构思想&#xff0c;其最基本的概念是存储程序概念&#xff0c;它奠定了现代计算机的结构基础。 功能部件: 计算机必须具备五大基本组成部件&#xff0c;包括&#xff1a;运…

程序员试用期转正工作总结

一、试用期工作总结 在公司的三个月试用期中&#xff0c;我完成了以下工作&#xff1a; 完成了XX个功能模块的开发&#xff0c;包括XX模块、XX模块和XX模块。参与了XX个项目的开发和上线&#xff0c;其中XX项目、XX项目和XX项目是我主导的。优化了现有系统的性能&#xff0c;特…

Anaconda定制Python编程并打包

本文主要介绍如何使用Anaconda定制一个Python编程环境并打包&#xff0c;方便编程环境迁移。 文章参考 谢作如 邱奕盛两位老师的《为信息科技教学定制一个Python编程环境》 * 开发不同的项目需要不同的库&#xff08;甚至不同版本&#xff09;&#xff0c;把所有的库安装到一…

mac录屏软件有哪些?分享5个实用软件

mac录屏软件有哪些&#xff1f;随着Mac电脑在创意和专业领域的使用日益普及&#xff0c;越来越多的用户需要录制屏幕内容以进行分享、演示或后期编辑。本文将为您介绍几款知名的Mac录屏软件&#xff0c;让您轻松实现屏幕录制的需求。 1.迅捷屏幕录像工具 这是一款功能强大的屏…

掌握Java Future模式及其灵活应用

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;今天咱们来聊聊Future。咱们程序员在日常工作中&#xff0c;肯定都遇到过需要处理耗时任务的情况&#xff0c;特别是在Java领域。比如说&#xff0c;小黑要从网络上下载数据&#xff0c;或者要执行一个计算密集型…

推理证明-条件等价式、德摩根律、双条件

对于命题逻辑部分来说&#xff0c;只需要掌握命题的符号化&#xff0c;以及如何进行推理证明即可。足矣。其他的都是一些基本的概念&#xff0c;扫一遍&#xff0c;记住即可。 对于什么是命题&#xff1a;陈述句、能判断、真值唯一 进行推理证明&#xff0c;我们需要记住以下…

渐进增强与优雅降级:提升用户体验的双重策略

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

NVIDIA GPU 与服务器型号匹配查询

NVIDIA GPU 与服务器型号匹配查询 1. Qualified System Catalog (认证服务器目录)2. NVIDIA L40S2.1. NVIDIA L40S GPU Specifications References 1. Qualified System Catalog (认证服务器目录) https://www.nvidia.cn/data-center/data-center-gpus/qualified-system-catal…

Vue入门四(组件介绍与定义|组件之间的通信)

文章目录 一、组件介绍与定义介绍定义1&#xff09;全局组件2&#xff09;局部组件 二、组件之间的通信1&#xff09;父组件向子组件传递数据2&#xff09;子传父通信 一、组件介绍与定义 介绍 组件(Component)是Vue.js 最强大的功能之一&#xff0c;它是html、css、js等的一个…