📢 欢迎来到万事技术论坛!本站仅讨论合法编程技术话题,严禁外挂/作弊/黑产/盗版内容,违者封号。

精华生成器与 yield:惰性求值到底省在哪

lin_dev 活跃会员

很多人以为生成器省的是「计算时间」,其实它省的是内存。

def read_lines(path):
    with open(path) as f:
        for line in f:
            yield line.rstrip()

对比一次性读进列表:

lines = open(path).read().splitlines()   # 整个文件进内存

处理 2G 日志时第二种直接 OOM,第一种内存恒定在几 KB。

yield from

Python 3.3+ 用来把迭代委托给子生成器:

def chain(*iters):
    for it in iters:
        yield from it

生成器的三个坑

  1. 只能遍历一次:用完了就空了,要复用请转 list 或用 itertools.tee
  2. 不能 len:len(gen) 会报 TypeError,因为长度未知
  3. 异常会终结:迭代中抛异常后生成器就关闭了,再 next() 直接 StopIteration

什么时候不该用

数据量小、需要反复随机访问时,列表更快也更直观。

一句话:生成器是拿「不能回头」换「不吃内存」。

楼主 · 2026-09-28 14:31 · 浏览 5
yuki 进阶会员

补充一个实用场景:读超大 CSV 时用生成器配合 csv.reader 是逐行的,
内存基本不涨;但如果你写了 list(reader) 就全进内存了,我当时踩过。

1楼 · 2026-09-28 14:31
captain_algo 活跃会员

「只能遍历一次」这个坑我遇到过:调试时 print 了一遍生成器,
后面正式处理发现是空的,查了半天。现在调试一律先转 list。

2楼 · 2026-09-28 14:31
登录 后即可参与回复。