第 32 课 · 阶段五 · 文件与异常
迭代器与生成器
迭代器与生成器是 Python 处理大数据的两件利器。这一课理解迭代协议,学会用 yield 写出省内存的生成器。
🎯 学完本课你将掌握
- 理解迭代器与可迭代对象
- 掌握 iter() 与 next()
- 用 yield 编写生成器函数
- 理解生成器省内存的原理
一、可迭代对象 vs 迭代器
可迭代对象:能 for 遍历的对象,如列表、字符串、字典、元组。
迭代器:能记住遍历位置、用 next() 一个一个取的对象。
概念演示.py
1lst = [1, 2, 3]2it = iter(lst) # 把可迭代对象变成迭代器3print(next(it)) # 14print(next(it)) # 25print(next(it)) # 36# print(next(it)) # StopIteration 取完了二、for 循环的本质
for x in 可迭代对象 的背后就是:先 iter() 得到迭代器,再不断 next(),遇到 StopIteration 就结束。
三、生成器函数:yield
函数里出现 yield,它就不再是普通函数,而是一个生成器:调用不执行,next() 一次执行到 yield 并暂停,再 next() 继续。
生成器入门.py
1def my_range(n):2 i = 03 while i < n:4 yield i # 产出 i 并暂停5 i += 167g = my_range(5)8print(next(g)) # 09print(next(g)) # 110for x in g: # 从上次暂停处继续11 print(x, end=" ") # 2 3 4四、生成器 vs 列表的内存对比
内存对比.py
1# 列表:一次性全部生成,占内存2big_list = [x * x for x in range(1000000)]34# 生成器:惰性生成,几乎不占内存5big_gen = (x * x for x in range(1000000))67print(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()56for line in read_big("note.txt"):7 print(line)六、yield 与 return 的区别
| 对比 | yield | return |
|---|---|---|
| 函数类型 | 生成器函数 | 普通函数 |
| 执行 | 暂停可恢复 | 立刻结束 |
| 返回值 | 产出一个个值 | 返回一次 |
| 内存 | 惰性省内存 | 一次性计算 |
七、常见错误与解决
常见错误与解决
| 错误现象 | 原因 / 解决方法 |
|---|---|
生成器只能遍历一次 | 生成器是单向的,用完就空;需要多次遍历就转成列表。 |
忘了 yield 写成 return | 函数里没有 yield 就退化成普通函数,不再惰性。 |
StopIteration 报错 | next() 取完了;在 for 里遍历会自动处理,别手动 next 过头。 |
✍️ 小练习
写一个生成器 fib_gen(n) 依次产出前 n 个斐波那契数;再用生成器表达式求 1 到 100 万平方和,体会内存优势。
📌 本节小结
迭代器用 iter()/next() 逐个取值;yield 让函数变成惰性生成器,边取边算、省内存。处理大数据与文件流,生成器是首选。