大家好,我是 亦难
今天我们把「迭代器」与「生成器」这两兄弟拆开揉碎,再用一条故事线串起来:

“如何优雅地读完一个 10 GB 的日志文件,而内存只占 20 MB?”

答案就在本文里。整篇阅读约 8 分钟,代码量控制在“一眼能看明白”的范围内。


一、为什么需要“惰性”?

想象你在视频网站刷剧:

  • 一次性加载全集 → 浏览器瞬间卡死(相当于把 10 GB 日志一次性读进内存)。
  • 点一集看一集 → 永远流畅(这就是惰性迭代)。

迭代器和生成器就是 Python 给你的“点一集看一集”的官方实现。


二、迭代器:最老实的搬运工

1️⃣ 定义与协议

迭代器必须同时满足两个魔法方法:

  • __iter__():返回自身。
  • __next__():返回下一个元素,没有就抛 StopIteration

2️⃣ 手写一个“倒计时迭代器”

class Countdown:
    def __init__(self, start):
        self.current = start

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < 0:
            raise StopIteration
        val = self.current
        self.current -= 1
        return val

# 使用
for num in Countdown(5):
    print(num, end=" ")   # 5 4 3 2 1 0

注意:迭代器是一次性用品,跑完一轮就“报废”。


三、生成器:语法糖里的黑科技

1️⃣ 生成器推导式

把列表推导式的 [] 换成 (),立刻变惰性:

gen = (i * 2 for i in range(5))
print(gen)            # <generator object ...>
print(next(gen))      # 0
print(list(gen))      # [2, 4, 6, 8]

2️⃣ yield 关键字

在普通函数里写 yield,它会在每次调用时冻结现场,下次从断点继续。

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

for f in fib(6):
    print(f, end=" ")   # 0 1 1 2 3 5

四、迭代器 vs 生成器:一张图看懂区别

维度 迭代器 生成器
实现方式 手写 __iter__ & __next__ 函数里写 yield
代码量
状态保存 手动 自动
内存占用 取决于实现 极低
典型用途 高度定制 快速惰性序列

五、实战:10 GB 日志文件的“零拷贝”读取

需求:统计日志里出现次数最多的 IP。
传统做法:readlines() 会把 10 GB 全部塞进内存 → 直接爆炸。
生成器做法:一行一行吐出来,内存恒定在几十 MB。

def read_lines(path):
    with open(path, 'r', encoding='utf-8') as f:
        for line in f:
            yield line

# 使用
ip_counter = {}
for line in read_lines('huge.log'):
    ip = line.split()[0]
    ip_counter[ip] = ip_counter.get(ip, 0) + 1
print(ip_counter.most_common(10))

六、常见误区 & 面试金句

  1. “迭代器只能遍历一次” —— 真;想再遍历请重新实例化。
  2. “生成器一定是迭代器,迭代器不一定是生成器” —— 真;yield 会自动实现迭代器协议。
  3. “惰性就一定快?” —— 不一定;惰性解决的是内存问题,不是CPU问题。

七、总结口诀

  • 迭代器:自己写,麻烦但灵活。
  • 生成器:用 yield,简单且省内存。
  • 何时用:数据量大、流式输入、管道式处理,优先考虑生成器。

✨ 明日预报

《时间与空间复杂度:用 O 记法给算法“称体重”》
明晚 ,带你用 15 分钟学会:

  • 如何一眼看出 O(n²)O(n log n) 的差距
  • 为什么二分查找永远比线性扫描“轻”
  • 空间换时间的经典套路与避坑指南

点个收藏,明晚一起“称代码的重量”!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐