Python进阶 - 生成器表达式 比列表推导式更省内存的写法
大家好欢迎来到我的技术博客 在这里我会分享学习笔记、实战经验与技术思考力求用简单的方式讲清楚复杂的问题。 本文将围绕Python进阶这个话题展开希望能为你带来一些启发或实用的参考。 无论你是刚入门的新手还是正在进阶的开发者希望你都能有所收获文章目录Python进阶生成器表达式如何比列表推导式更省内存 列表推导式快速但“昂贵”的写法 生成器表达式按需生成内存友好 延迟求值机制详解 内存对比一图胜千言 实际应用场景为什么生成器如此重要1️⃣ 处理大文件如日志分析❌ 错误做法读取整个文件到内存✅ 正确做法使用生成器逐行处理2️⃣ 无限序列生成数学计算❌ 列表无法表示无限序列✅ 生成器完美解决这个问题3️⃣ 数据管道与链式处理⚙️ 底层原理剖析生成器是如何工作的 生成器的本质协程Coroutine 性能测试真实数据对比️ 高级技巧生成器与其他工具结合✅ 与 map() 和 filter() 联用✅ 使用 sum() 直接消费生成器 常见误区与注意事项❗ 1. 不能重复使用❗ 2. 无法索引访问 总结何时该用生成器 拓展阅读推荐✅ 最后建议Python进阶生成器表达式如何比列表推导式更省内存在现代编程中内存管理是决定程序性能与可扩展性的关键因素之一。尤其是在处理大规模数据时选择合适的语法结构可以显著影响程序的运行效率和资源消耗。今天我们就来深入探讨一个看似简单却极为重要的概念——生成器表达式Generator Expression与列表推导式List Comprehension之间的差异特别是它们在内存使用上的根本区别。 本文将带你从底层原理出发通过真实代码示例、性能对比分析以及可视化图表全面揭示为何生成器表达式在多数场景下是更优的选择。无论你是初学者还是资深开发者这篇文章都将为你提供实用且深刻的理解。 列表推导式快速但“昂贵”的写法让我们先回顾一下最常见的数据构建方式——列表推导式。# 普通列表推导式示例squares[x**2forxinrange(1000000)]print(f列表长度:{len(squares)})这段代码会立即创建一个包含一百万个平方数的列表并将其全部加载到内存中。虽然语法简洁优雅但它有一个致命缺点✅ 所有元素一次性生成并存储在内存中❌ 占用大量内存空间可能引发MemoryError我们可以通过sys.getsizeof()来查看实际占用内存importsys squares[x**2forxinrange(1000000)]print(f列表大小:{sys.getsizeof(squares)}字节)# 输出约 8,000,000 字节 这意味着即使你的电脑有16GB内存在处理千万级数据时也可能因内存不足而崩溃。 小贴士sys.getsizeof()返回的是对象本身占用的字节数不包括其内容引用的额外开销。 生成器表达式按需生成内存友好现在让我们看看同样的功能如何用生成器表达式实现# 生成器表达式squares_gen(x**2forxinrange(1000000))print(f生成器对象大小:{sys.getsizeof(squares_gen)}字节)# 输出仅约 104 字节 看到了吗生成器对象本身的大小只有104字节而对应的列表却占用了超过800万字节这背后的原因在于生成器表达式不会立即计算所有值而是延迟求值Lazy Evaluation。 延迟求值机制详解当定义一个生成器表达式时Python只保存了表达式逻辑和起始状态真正的计算发生在每次调用next()或迭代时。# 逐步获取值gen(x**2forxinrange(5))print(next(gen))# 0print(next(gen))# 1print(next(gen))# 4print(next(gen))# 9print(next(gen))# 16# print(next(gen)) # StopIteration 异常抛出 关键点生成器不会预先把所有结果算出来。每次调用next()才执行一次计算。用完即丢无需保留中间结果。这种特性使得它特别适合处理大数据流、文件读取、网络请求等场景。 内存对比一图胜千言下面是一个用 Mermaid 绘制的内存占用对比图直观展示两种方式的差异一次性生成按需生成列表推导式内存中存放完整列表生成器表达式仅保存生成逻辑占用大量内存仅占用极小内存可能触发 MemoryError支持无限序列 图解说明左侧的“列表推导式”需要预先分配全部内存一旦数据过大就容易崩溃。右侧的“生成器表达式”几乎不占用额外内存只记录如何生成下一个值。✅ 推荐当你只需要遍历一次数据或不确定数据总量时优先使用生成器。 实际应用场景为什么生成器如此重要1️⃣ 处理大文件如日志分析假设你有一个超大的日志文件100MB以上你想找出所有包含ERROR的行。❌ 错误做法读取整个文件到内存withopen(huge_log.txt,r)asf:linesf.readlines()# 一次性读入内存errors[line.strip()forlineinlinesifERRORinline]⚠️ 风险如果文件很大可能导致程序崩溃。✅ 正确做法使用生成器逐行处理deferror_lines(filename):withopen(filename,r)asf:forlineinf:ifERRORinline:yieldline.strip()# 使用生成器forerrorinerror_lines(huge_log.txt):print(error)✅ 优势不需要把整个文件加载进内存。只在需要时读取一行处理一行。支持任意大小的日志文件。 更多信息参考Python 官方文档 - 文件操作2️⃣ 无限序列生成数学计算有时我们需要生成一个无限长的数列比如斐波那契数列。❌ 列表无法表示无限序列# 这会永远运行下去且最终耗尽内存fib_list[]a,b0,1whileTrue:fib_list.append(a)a,bb,ab✅ 生成器完美解决这个问题deffibonacci():a,b0,1whileTrue:yielda a,bb,ab# 取前10个斐波那契数fib_genfibonacci()first_ten[next(fib_gen)for_inrange(10)]print(first_ten)# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 重点生成器允许我们“想象”无限序列而不必真正存储它们。 深入了解斐波那契数列与生成器 | GeeksforGeeks3️⃣ 数据管道与链式处理在数据处理流程中常常需要对数据进行多个步骤的转换。生成器允许我们将这些操作串联起来形成高效的“数据流水线”。# 假设有大量用户数据users[{name:Alice,age:25,active:True},{name:Bob,age:30,active:False},{name:Charlie,age:35,active:True},# ... 无数条]# 使用生成器链式处理deffilter_active(users):return(userforuserinusersifuser[active])defget_names(users):return(user[name]foruserinusers)defuppercase(names):return(name.upper()fornameinnames)# 构建流水线pipelineuppercase(get_names(filter_active(users)))# 只有在遍历时才真正执行fornameinpipeline:print(name) 优点所有操作都是惰性执行。中间结果不会被缓存。内存使用保持低位。⚙️ 底层原理剖析生成器是如何工作的要理解生成器的高效性我们必须深入其底层机制。 生成器的本质协程CoroutinePython中的生成器实际上是一种特殊的函数它可以在执行过程中暂停并恢复。defcounter():i0whileTrue:print(f开始第{i}次 yield)yieldi i1print(f继续循环当前为{i})ccounter()print(next(c))# 0print(next(c))# 1输出开始第 0 次 yield 0 继续循环当前为 1 开始第 1 次 yield 1 关键机制yield使函数暂停并返回值。下次调用next()时函数从上次暂停处继续执行。函数的状态变量、位置被自动保存。这就是所谓的“状态保留”也是生成器能节省内存的核心原因。 性能测试真实数据对比下面我们进行一次真实的性能测试比较列表推导式与生成器表达式的内存和时间开销。importtimeimportsys# 测试规模N100000# 1. 列表推导式starttime.time()list_comp[x*21forxinrange(N)]list_timetime.time()-start list_memsys.getsizeof(list_comp)# 2. 生成器表达式starttime.time()gen_expr(x*21forxinrange(N))gen_timetime.time()-start gen_memsys.getsizeof(gen_expr)# 3. 实际遍历生成器所花时间starttime.time()list_from_genlist(gen_expr)gen_iter_timetime.time()-startprint(*50)print( 性能对比报告)print(*50)print(f列表推导式耗时:{list_time:.4f}秒)print(f生成器表达式初始化耗时:{gen_time:.4f}秒)print(f生成器遍历耗时:{gen_iter_time:.4f}秒)print(f列表大小:{list_mem:,}字节)print(f生成器大小:{gen_mem:,}字节)print(f内存节省比例:{(1-gen_mem/list_mem)*100:.1f}%) 预期输出示例 性能对比报告 列表推导式耗时: 0.0234 秒 生成器表达式初始化耗时: 0.0001 秒 生成器遍历耗时: 0.0241 秒 列表大小: 800,000 字节 生成器大小: 104 字节 内存节省比例: 99.9%✅ 结论列表推导式在创建阶段慢得多因为要计算所有值。生成器初始化几乎无成本。最终遍历时间相近但内存使用差距巨大。️ 高级技巧生成器与其他工具结合✅ 与map()和filter()联用# 传统方式numbers[1,2,3,4,5]doubled[x*2forxinnumbersifx%21]# 生成器方式doubled_genmap(lambdax:x*2,filter(lambdax:x%21,numbers))# 两者等价但生成器更省内存✅ 使用sum()直接消费生成器# 计算前100万个奇数的和totalsum(xforxinrange(1,2000000,2))print(total)# 1000000000000 亮点sum()会自动迭代生成器无需显式循环。 常见误区与注意事项尽管生成器有很多优点但也有一些陷阱需要注意❗ 1. 不能重复使用gen(x**2forxinrange(3))print(list(gen))# [0, 1, 4]print(list(gen))# [] —— 空了 解决方案重新创建生成器或使用itertools.tee()分叉。fromitertoolsimporttee gen(x**2forxinrange(3))g1,g2tee(gen,2)print(list(g1))# [0, 1, 4]print(list(g2))# [0, 1, 4]❗ 2. 无法索引访问gen(xforxinrange(5))# print(gen[2]) # ❌ 报错generator object does not support indexing 如果你需要随机访问请转为列表但牺牲内存。 总结何时该用生成器场景推荐方式遍历一次数据✅ 生成器表达式需要多次遍历⚠️ 谨慎使用考虑tee()需要索引访问❌ 不推荐应转为列表处理大文件/流数据✅ 必须使用生成器无限序列✅ 唯一可行方案短期临时计算✅ 生成器或列表均可 拓展阅读推荐如果你想进一步学习生成器和迭代器相关知识以下资源非常值得一看Python 官方文档 - Generator ExpressionsReal Python - Generators in PythonGeeksforGeeks - Python Generators✅ 最后建议在日常开发中养成“默认使用生成器表达式”的习惯除非你明确知道需要重复遍历或随机访问。# ✅ 推荐写法totalsum(x**2forxinrange(1000000))# ❌ 不推荐写法除非必须totalsum([x**2forxinrange(1000000)]) 一句话总结生成器表达式不是“更快”的选择而是“更聪明”的选择——它用极少的内存完成了几乎相同的工作。 让我们从今天开始写出更高效、更优雅、更可持续的代码吧✨ 代码改变世界而生成器正在悄悄优化这个世界。 感谢你读到这里 技术之路没有捷径但每一次阅读、思考和实践都在悄悄拉近你与目标的距离。 如果本文对你有帮助不妨 点赞、收藏、分享给更多需要的朋友 欢迎在评论区留下你的想法、疑问或建议我会一一回复我们一起交流、共同成长 关注我不错过下一篇干货我们下期再见✨

相关新闻

跨平台开源IPTV播放器IPTVnator:打造专业级电视流媒体体验的完整解决方案

跨平台开源IPTV播放器IPTVnator:打造专业级电视流媒体体验的完整解决方案

跨平台开源IPTV播放器IPTVnator:打造专业级电视流媒体体验的完整解决方案 【免费下载链接】iptvnator :tv: Cross-platform IPTV player application with multiple features, such as support of m3u and m3u8 playlists, favorites, TV guide, TV archive/catchup…

2026/8/12 21:17:03 阅读更多 →
NP0015:国王小码哥

NP0015:国王小码哥

小朋友们吃到了小码哥分享的糖果,大家都很开心,于是小朋友们决定,在今天的游戏中,让小码哥扮演国王。国王小码哥要率领自己的军队与入侵的敌人交战,因为是小朋友,所以作战的方式很简单——剪刀石头布。其中…

2026/8/12 21:17:03 阅读更多 →
Python进阶 - re模块的search方法 查找字符串中的第一个匹配

Python进阶 - re模块的search方法 查找字符串中的第一个匹配

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Python进阶这个话题展开,希望能为你带来一些…

2026/8/12 21:16:02 阅读更多 →

最新新闻

SQL Server存储过程开发实战:从零到精通,构建高效数据库业务逻辑

SQL Server存储过程开发实战:从零到精通,构建高效数据库业务逻辑

1. 项目概述:为什么存储过程是SQL Server开发者的“瑞士军刀” 在数据库开发领域,尤其是处理SQL Server时,存储过程(Stored Procedure)绝对是一个绕不开的核心概念。你可以把它理解为一个预编译的、存储在数据库服务器…

2026/8/12 22:04:39 阅读更多 →
mermaid-to-excalidraw支持哪些图表类型?一次性了解所有可用功能

mermaid-to-excalidraw支持哪些图表类型?一次性了解所有可用功能

mermaid-to-excalidraw支持哪些图表类型?一次性了解所有可用功能 【免费下载链接】mermaid-to-excalidraw Generate Excalidraw diagrams from Mermaid 项目地址: https://gitcode.com/gh_mirrors/me/mermaid-to-excalidraw mermaid-to-excalidraw是一款强大…

2026/8/12 22:04:39 阅读更多 →
从入门到精通:nodejs-polars核心功能与API详解

从入门到精通:nodejs-polars核心功能与API详解

从入门到精通:nodejs-polars核心功能与API详解 【免费下载链接】nodejs-polars nodejs front-end of polars 项目地址: https://gitcode.com/gh_mirrors/no/nodejs-polars nodejs-polars是一个基于Polars的Node.js前端库,提供了极速的数据处理能力…

2026/8/12 22:04:39 阅读更多 →
追番神器技术解析:从资源聚合到流媒体播放的工程实践

追番神器技术解析:从资源聚合到流媒体播放的工程实践

最近在追番时,是不是总感觉资源难找、画质参差不齐,或者新番更新不及时?作为一名同样热爱二次元的技术爱好者,我深知一个好用的追番工具对体验的提升有多大。今天要分享的这款工具,可以说是我近期发现的“宝藏”&#…

2026/8/12 22:04:39 阅读更多 →
网盘系统账号管理:密码找回、退出登录与头像上传实现

网盘系统账号管理:密码找回、退出登录与头像上传实现

1. 项目概述 "easy网盘学习"系列教程的第三部分聚焦用户账号管理功能实现,包含找回密码、退出登录和上传头像三大核心模块。作为网盘类应用的基础功能,这些模块直接关系到用户体验和账号安全性。我在开发过程中发现,很多新手开发者…

2026/8/12 22:04:39 阅读更多 →
VCF文件处理终极工具:vcflib一站式解决解析与变异分析难题

VCF文件处理终极工具:vcflib一站式解决解析与变异分析难题

VCF文件处理终极工具:vcflib一站式解决解析与变异分析难题 【免费下载链接】vcflib C library and cmdline tools for parsing and manipulating VCF files with python and zig bindings 项目地址: https://gitcode.com/gh_mirrors/vcf/vcflib 在生物信息学…

2026/8/12 22:03:39 阅读更多 →

日新闻

Ubuntu 22.04安装与使用tree命令:高效管理Linux目录结构

Ubuntu 22.04安装与使用tree命令:高效管理Linux目录结构

1. 为什么需要一个“目录树”工具?在Linux世界里,尤其是Ubuntu这样的发行版,命令行是很多人的主战场。我们每天都要和文件、目录打交道。ls命令是查看目录内容的首选,它简洁、高效,能列出文件名、权限、大小等关键信息…

2026/8/12 9:33:34 阅读更多 →
博思AI智能体:意图识别、思考链与性能优化的工程实践

博思AI智能体:意图识别、思考链与性能优化的工程实践

在AI应用从“能用”走向“好用”的进程中,系统的响应速度、决策透明度与高并发稳定性是决定用户体验的关键。博思AI智能体近期完成了一次重要的专项优化,聚焦于意图识别、思考链展示与全链路压测三大核心领域,将系统从功能实现推向了工程卓越…

2026/8/12 9:33:34 阅读更多 →
子代理架构:AI智能体任务分解与协同执行的核心原理与实践

子代理架构:AI智能体任务分解与协同执行的核心原理与实践

1. 项目概述:为什么我们需要“子代理”?最近在折腾各种AI应用和自动化流程时,我越来越频繁地遇到一个瓶颈:单个AI智能体(Agent)的能力边界。无论是处理复杂的多步骤任务,还是需要同时调用多个专…

2026/8/12 9:33:34 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/12 1:11:09 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/12 1:11:09 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/12 1:11:08 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/11 17:09:45 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/12 1:11:10 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/11 17:09:45 阅读更多 →