生成器比列表节省内存达数量级,如range(10**6)仅占几十字节,而等价列表占用约8MB;必须用yield的场景包括处理大文件、递归结构、无限序列及管道式惰性求值链。

生成器比列表节省多少内存?
生成器对象本身只占几十字节,而等价的列表在创建时就得把所有元素装进内存。比如 range(10**6) 返回的是生成器(Python 3),但 [x for x in range(10**6)] 会立刻分配约 8MB 内存(取决于元素类型和系统)。实际差距不是“省一点”,而是“差一个数量级”——尤其当数据源来自文件、数据库或网络流时,列表可能直接 OOM。
什么时候必须用 yield 而不是返回列表?
典型场景是处理无法一次性加载的数据:
- 读大文件时逐行或逐块处理:
yield每次只保留一行字符串,而不是把整个文件读进list - 递归结构遍历(如树、嵌套 JSON):避免中间结果堆积,用生成器展开子节点
- 无限序列(如斐波那契、素数流):根本没法用列表表示
- 管道式处理链:
filter+map+ 自定义生成器可形成惰性求值链,全程无临时列表
yield 和 return 混用会怎样?
函数里只要出现 yield,Python 就把它编译成生成器函数,哪怕同时有 return。但要注意:
-
return value在生成器中会触发StopIteration,且value会成为异常的value属性(Python 3.3+),不能被next()拿到 -
return后面的代码不会执行,但yield之后仍可继续写逻辑,只要没被提前return中断 - 别试图在生成器里用
return x当“返回最终结果”——它不等价于函数返回值,调用方拿不到
生成器用完就失效,怎么重复使用?
生成器是一次性的,迭代完就空了,再次 next() 必抛 StopIteration。这不是 bug,是设计使然。常见应对方式:
系统优势: 1、 使用全新ASP.Net+c#和三层结构开发. 2、 可生成各类静态页面(html,htm,shtm,shtml和.aspx) 3、 管理后台风格模板自由选择,界面精美 4、 风格模板每月更新多套,还可按需定制 5、 独具的缓存技术加快网页浏览速度 6、 智能销售统计,图表分析 7、 集成国内各大统计系统 8、 多国语言支持,内置简体繁体和英语 9、 UTF-8编码,可使用于全球
立即学习“Python免费学习笔记(深入)”;
- 重新调用生成器函数,得到新生成器(最常用)
- 用
itertools.tee()分叉,但注意它内部会缓存已取数据,内存开销可能反弹 - 如果只是需要多次遍历,且数据量可控,不如改用元组或冻结集合——生成器的优势本就不在“可重用”
最容易被忽略的是:生成器的“惰性”和“一次性”是一体两面。想绕过后者,往往就牺牲了前者。









