别小看“拖延症”:Python 惰性(Lazy)求值的 9 种用法
off999 2025-09-04 15:30 54 浏览 0 评论
如果要选出一个最能体现 Python 优雅之处的特性,我会毫不犹豫地选择——惰性( lazy)求值。
所谓惰性求值(Lazy Evaluation),就是将计算延迟到真正需要的时候才执行。这种机制让 Python 能够避免不必要的工作、节省内存、加快响应速度,甚至还能实现一些听起来不可思议的事情,比如生成一个无限长的列表。
更妙的是,在 Python 中实现惰性求值几乎不需要复杂的语法或晦涩的技巧,一切都简单、优雅,却又极具威力。
在这篇文章里,我们将一起探索 Python 内置的 9 个惰性求值特性,它们会在不声不响中显著优化你的代码。读完并掌握这些实用示例后,你会发现:让 Python 应用高效扩展,其实可以轻松实现。
1.生成器(Generators):处理海量数据的利器
生成器是 Python 中最知名的惰性求值特性之一。它允许我们在迭代序列时无需一次性将整个序列加载到内存中。这在处理大规模数据集、流式数据,甚至无限数据流时,尤其有用。
例如,当一个文件大到无法一次性读入时,生成器可以帮我们节省内存:
这段代码的核心是 yield 关键字。与一次性计算并返回所有结果的 return 不同,yield 会让函数返回一个生成器对象,并在每次产出数据后暂停执行,保留当前状态,下次迭代时再继续执行。
因此,上面的例子中,我们不会一次性返回整个文件内容,而是每次只将一行加载到内存中,这在处理大文件时能显著降低内存消耗。
当然,生成器也有取舍:数据是顺序流式读取的,因此不能像列表一样随机访问,比如不能直接跳到第 1000 行而不先读取前 999 行。
除了读取大数据集,我们还可以用生成器来构造数据集。比如著名的斐波那契数列是一个无限序列,但借助生成器,我们可以轻松实现一个“按需生成”的版本:
这个生成器会在你需要时才产出下一个斐波那契数,而不是一次性生成全部(这本来就是不可能的)。
2.生成器表达式(Generator Expressions):轻松获取内存友好的可迭代对象
除了用 yield 创建生成器,Python 还提供了另一种更简洁的方式——生成器表达式。
它的语法和列表推导式(List Comprehension)几乎一模一样,只是将方括号 [] 换成圆括号 (),就能让它具备惰性求值的特性。
如果需要,可以随时用 list() 方法将生成器表达式转换为列表:
生成器表达式的优势在于:不会一次性生成所有元素,因此相比列表更加节省内存。
来看一个简单的内存占用对比:
可见,生成器表达式在处理大规模数据时几乎不占额外内存,非常适合流式计算或内存受限的场景。
3. itertools模块:惰性迭代的工具箱
Python 内置的 itertools 模块提供了一组高效迭代的工具,其中很多都利用了惰性求值的特性。它们不仅节省内存,还能让我们用极少的代码实现复杂的迭代逻辑。下面是几个常用方法:
① 无限计数器 — itertools.count(start=0, step=1)
生成一个无限递增(或递减)的数字序列:
② 无限循环 — itertools.cycle(iterable)
让一个可迭代对象无限循环,无需写笨拙的死循环:
③ 重复元素 — itertools.repeat(object, times=None)
重复生成同一个对象,可选次数限制:
④ 惰性切片 — itertools.islice(iterable, start, stop[, step])
类似 list[start:stop],但不一次性生成所有数据:
⑤ 惰性拼接 — itertools.chain(*iterables)
将多个可迭代对象拼接成一个序列,但不会一次性加载到内存:
itertools 像是 Python 的惰性迭代“工具箱”,不仅能帮我们节省内存,还能让循环逻辑更优雅、更高效。
4. range():按需生成的数字序列
range() 是 Python 中最经典的惰性求值案例之一。它不会一次性生成所有数字,而是在需要时才生成对应的值。
来看一个内存占用对比:
可以看到,即使是生成一百万个数字,range() 也只占用 48 字节 内存,而列表却需要 8 MB 以上。这就是惰性求值带来的巨大优势:数据不提前占用内存,只在迭代时生成。
因此,在需要遍历大范围数字时,优先考虑 range() 而不是一次性生成完整列表,这能显著降低内存开销。
5. map()和 filter():惰性的高阶函数
Python 内置的 map() 和 filter() 都是高阶函数(即可以接收函数作为参数),同时它们也是惰性求值的代表:并不会一次性计算所有结果,而是返回一个迭代器,在遍历时才逐个执行计算。
这种特性使它们在处理大规模数据集时既节省内存,又保持较高性能。
惰性映射 — map()
map() 会将一个函数按需应用到序列的每个元素上:
惰性过滤 — filter()
filter() 会使用一个条件函数按需筛选元素:
与列表推导式相比,map() 和 filter() 在大数据场景下的内存占用更低,因为它们不会立即生成整个结果集,而是边迭代边计算。这让它们在数据流处理、日志分析等场景中非常实用。
6. zip():惰性组合多个可迭代对象
zip() 用于并行迭代多个可迭代对象,会按顺序生成由对应元素组成的元组。
它返回的是一个惰性迭代器,只有在调用 next() 或遍历时,才会按需生成下一个组合。
默认行为:取最短序列长度
zip() 会在最短的可迭代对象结束时停止:
zip_longest():补齐缺失元素
如果希望按最长的可迭代对象对齐,可以使用 itertools.zip_longest(),并指定 fillvalue 来填充缺失值:
由于 zip() 是惰性生成的,因此即使组合的是大型数据集,也不会一次性加载到内存中,非常适合多数据源同步迭代的场景。
7. enumerate():惰性获取索引与值
enumerate() 是 Python 中非常常用的迭代工具,尤其是在需要同时获取索引和值时。
它返回的是一个惰性迭代器,不会一次性生成所有索引—值对,而是在遍历时按需生成:
相比手动维护一个计数器变量,enumerate() 不仅代码更简洁,而且由于它是惰性生成的,内存占用也更低,非常适合在处理大规模可迭代对象时使用。
8. 字典视图(Dictionary Views)也是惰性的
当你调用 dict.keys()、dict.values() 或 dict.items() 时,返回的并不是一个列表,而是一个视图对象(view object)。
这意味着:
1.不会生成数据的完整副本。
2.实时反映字典的变化。
3.惰性且内存高效。
内存占用对比实验
如结果所示,字典视图对象的占用仅为几十字节,与直接转换成列表相比,节省了大量内存。也就是说,即使我们没意识到,它们也在悄悄帮我们优化内存使用。
9. 类型注解(Type Annotations)的惰性求值
Python 3.14 引入了类型注解惰性求值的重要更新:函数、类和模块的注解不再在定义时立即执行。
相反,这些注解会被存储为一种特殊的“延迟形式”,只有在真正需要时才会被求值。
举个例子,定义如下函数:
在 Python 3.14 之前,MyType 和 OtherType 会在模块导入时立即求值,这可能导致导入时间变长或引发循环依赖。
而从 Python 3.14 开始,这种求值会被延迟,直到运行时真正需要进行类型检查或反射操作时才执行(相关内容见 PEP 649 和 PEP 749)。
之前的 Python 版本(3.7–3.11)中,我们需要通过一句特殊的导入来开启这项惰性特性:
而在 Python 3.14 及以后,类型注解默认就是惰性求值,无需再额外声明。
这项改进不仅优化了程序启动速度,还减少了因类型注解引起的依赖问题,让类型提示更好用、更高效。
结语:善用 Python 的惰性求值,做更高效的开发者
Python 的惰性求值机制,能够显著提升代码的性能和内存效率。无论你是处理海量数据、构建无限循环,还是管理复杂的类型注解,理解并合理利用惰性求值,都能让你成为一个更懂资源管理的开发者。
当然,我们也要牢记,惰性求值并非万能,某些场景下,**立即求值(eager evaluation)**反而更合适,比如:
- 需要马上得到完整结果时
- 数据集较小,性能开销不大时
- 需要多次遍历同一数据时
- 内存使用不是瓶颈时
作为开发者,关键是根据实际需求灵活取舍,写出既优雅又高效的 Python 代码。
相关推荐
- 安全教育登录入口平台(安全教育登录入口平台官网)
-
122交通安全教育怎么登录:122交通网的注册方法是首先登录网址http://www.122.cn/,接着打开网页后,点击右上角的“个人登录”;其次进入邮箱注册,然后进入到注册页面,输入相关信息即可完...
- 大鱼吃小鱼经典版(大鱼吃小鱼经典版(经典版)官方版)
-
大鱼吃小鱼小鱼吃虾是于谦跟郭麒麟的《我的棒儿呢?》郭德纲说于思洋郭麒麟作诗的相声,最后郭麒麟做了一首,师傅躺在师母身上大鱼吃小鱼小鱼吃虾虾吃水水落石出师傅压师娘师娘压床床压地地动山摇。...
-
- 哪个软件可以免费pdf转ppt(免费的pdf转ppt软件哪个好)
-
要想将ppt免费转换为pdf的话,我们建议大家可以下一个那个wps,如果你是会员的话,可以注册为会员,这样的话,在wps里面的话,就可以免费将ppt呢转换为pdfpdf之后呢,我们就可以直接使用,不需要去直接不需要去另外保存,为什么格式转...
-
2026-02-04 09:03 off999
- 电信宽带测速官网入口(电信宽带测速官网入口app)
-
这个网站看看http://www.swok.cn/pcindex.jsp1.登录中国电信网上营业厅,宽带光纤,贴心服务,宽带测速2.下载第三方软件,如360等。进行在线测速进行宽带测速时,尽...
- 植物大战僵尸95版手机下载(植物大战僵尸95 版下载)
-
1可以在应用商店或者游戏平台上下载植物大战僵尸95版手机游戏。2下载教程:打开应用商店或者游戏平台,搜索“植物大战僵尸95版”,找到游戏后点击下载按钮,等待下载完成即可安装并开始游戏。3注意:确...
- 免费下载ppt成品的网站(ppt成品免费下载的网站有哪些)
-
1、Chuangkit(chuangkit.com)直达地址:chuangkit.com2、Woodo幻灯片(woodo.cn)直达链接:woodo.cn3、OfficePlus(officeplu...
- 2025世界杯赛程表(2025世界杯在哪个国家)
-
2022年卡塔尔世界杯赛程公布,全部比赛在卡塔尔境内8座球场举行,2022年,决赛阶段球队全部确定。揭幕战于当地时间11月20日19时进行,由东道主卡塔尔对阵厄瓜多尔,决赛于当地时间12月18日...
- 下载搜狐视频电视剧(搜狐电视剧下载安装)
-
搜狐视频APP下载好的视频想要导出到手机相册里方法如下1、打开手机搜狐视频软件,进入搜狐视频后我们点击右上角的“查找”,找到自已喜欢的视频。2、在“浏览器页面搜索”窗口中,输入要下载的视频的名称,然后...
- 永久免费听歌网站(丫丫音乐网)
-
可以到《我爱音乐网》《好听音乐网》《一听音乐网》《YYMP3音乐网》还可以到《九天音乐网》永久免费听歌软件有酷狗音乐和天猫精灵,以前要跳舞经常要下载舞曲,我从QQ上找不到舞曲下载就从酷狗音乐上找,大多...
- 音乐格式转换mp3软件(音乐格式转换器免费版)
-
有两种方法:方法一在手机上操作:1、进入手机中的文件管理。2、在其中选择“音乐”,将显示出手机中的全部音乐。3、点击“全选”,选中所有音乐文件。4、点击屏幕右下方的省略号图标,在弹出菜单中选择“...
- 电子书txt下载(免费的最全的小说阅读器)
-
1.Z-library里面收录了近千万本电子书籍,需求量大。2.苦瓜书盘没有广告,不需要账号注册,使用起来非常简单,直接搜索预览下载即可。3.鸠摩搜书整体风格简洁清晰,书籍资源丰富。4.亚马逊图书书籍...
- 最好免费观看高清电影(播放免费的最好看的电影)
-
在目前的网上选择中,IMDb(互联网电影数据库)被认为是最全的电影网站之一。这个网站提供了各种类型的电影和电视节目的海量信息,包括剧情介绍、演员表、评价、评论等。其还提供了有关电影制作背后的详细信息,...
- 孤单枪手2简体中文版(孤单枪手2简体中文版官方下载)
-
要将《孤胆枪手2》游戏的征兵秘籍切换为中文,您可以按照以下步骤进行操作:首先,打开游戏设置选项,通常可以在游戏主菜单或游戏内部找到。然后,寻找语言选项或界面选项,点击进入。在语言选项中,选择中文作为游...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
win7系统还原步骤图解(win7还原电脑系统的步骤)
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
python入门到脱坑 输入与输出—str()函数
-
16949认证费用是多少(16949审核员太难考了)
-
linux软件(linux软件图标)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
windows7旗舰版多少钱(win7旗舰版要多少钱)
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
