第 32 课 · 阶段五 · 文件与异常

迭代器与生成器

迭代器与生成器是 Python 处理大数据的两件利器。这一课理解迭代协议,学会用 yield 写出省内存的生成器。

第 32 课阶段五 · 文件与异常难度:进阶建议时长:35 分钟关键词:iter · next · yield · 生成器

🎯 学完本课你将掌握

  • 理解迭代器与可迭代对象
  • 掌握 iter() 与 next()
  • 用 yield 编写生成器函数
  • 理解生成器省内存的原理

一、可迭代对象 vs 迭代器

可迭代对象:能 for 遍历的对象,如列表、字符串、字典、元组。

迭代器:能记住遍历位置、用 next() 一个一个取的对象。

概念演示.py
1lst = [1, 2, 3]
2it = iter(lst) # 把可迭代对象变成迭代器
3print(next(it)) # 1
4print(next(it)) # 2
5print(next(it)) # 3
6# print(next(it)) # StopIteration 取完了

二、for 循环的本质

for x in 可迭代对象 的背后就是:先 iter() 得到迭代器,再不断 next(),遇到 StopIteration 就结束。

三、生成器函数:yield

函数里出现 yield,它就不再是普通函数,而是一个生成器:调用不执行,next() 一次执行到 yield 并暂停,再 next() 继续。

生成器入门.py
1def my_range(n):
2 i = 0
3 while i < n:
4 yield i # 产出 i 并暂停
5 i += 1
6
7g = my_range(5)
8print(next(g)) # 0
9print(next(g)) # 1
10for x in g: # 从上次暂停处继续
11 print(x, end=" ") # 2 3 4

四、生成器 vs 列表的内存对比

内存对比.py
1# 列表:一次性全部生成,占内存
2big_list = [x * x for x in range(1000000)]
3
4# 生成器:惰性生成,几乎不占内存
5big_gen = (x * x for x in range(1000000))
6
7print(sum(big_gen)) # 两者结果一样,生成器省内存
✅ 要点
处理超大文件、超大数据流时用生成器,能极大降低内存占用。惰性求值是它的灵魂。

五、实战:逐行读取大文件

生成器读文件.py
1def read_big(path):
2 with open(path, "r", encoding="utf-8") as f:
3 for line in f: # 本身就在逐行读
4 yield line.strip()
5
6for line in read_big("note.txt"):
7 print(line)

六、yield 与 return 的区别

对比yieldreturn
函数类型生成器函数普通函数
执行暂停可恢复立刻结束
返回值产出一个个值返回一次
内存惰性省内存一次性计算

七、常见错误与解决

常见错误与解决

错误现象原因 / 解决方法
生成器只能遍历一次生成器是单向的,用完就空;需要多次遍历就转成列表。
忘了 yield 写成 return函数里没有 yield 就退化成普通函数,不再惰性。
StopIteration 报错next() 取完了;在 for 里遍历会自动处理,别手动 next 过头。
✍️ 小练习
写一个生成器 fib_gen(n) 依次产出前 n 个斐波那契数;再用生成器表达式求 1 到 100 万平方和,体会内存优势。
📌 本节小结
迭代器用 iter()/next() 逐个取值;yield 让函数变成惰性生成器,边取边算、省内存。处理大数据与文件流,生成器是首选。