生成器
生成器是一种特殊的迭代器,它不需要你手动去实现迭代器协议(即 iter() 和 next() 方法)。它允许你用一种更简单、更像普通函数的方式来生成一个值的序列。
生成器的核心思想是 “懒加载” (Lazy Evaluation) 或 “延迟计算”。它不会一次性在内存中创建并存储所有元素,而是在你请求下一个元素时才实时生成它。
为什么要使用生成器?
生成器最主要的优点是内存效率极高。想象一下,你需要处理一个包含一百万个元素的序列。
- 使用列表:会立即在内存中创建并存储这一百万个元素,占用大量内存。
- 使用生成器:它只在你需要时才逐一生成元素。在任何时刻,内存中只有一个元素存在,极大地节约了内存资源。
这使得生成器非常适合处理:
- 大规模数据集:如大型日志文件、数据库查询结果等。
- 无限序列:例如,生成一个永不停止的斐波那契数列。
- 数据流处理:在数据处理管道中,数据可以像水流一样通过各个生成器节点,而无需将整个数据集加载到内存中。
创建生成器
主要有两种方式可以创建生成器:
- 生成器函数 (Generator Functions) 这是最常见的方式。一个普通的函数,只要包含了 yield 关键字,它就变成了一个生成器函数。
yield 关键字:这是生成器的魔法所在。yield 的作用类似于 return,但它并不会终止函数。相反,它会“暂停”函数的执行,并将其当前状态(包括局部变量)保存下来,然后将 yield 后面的值返回给调用者。当下次请求值时(例如通过 next() 或 for 循环),函数会从上次暂停的地方继续执行。
1 | def countdown(n): |
注意, 调用generator函数会创建一个generator对象,多次调用generator函数会创建多个相互独立的generator。假如在上面的代码中这样做:
1 | print(next(countdown(3))) # 每次调用都会创建一个新的生成器对象, 所以每次都是输出 3 |
- 生成器表达式 (Generator Expressions) 生成器表达式是列表生成式的近亲,语法上非常相似,但它返回的是一个生成器对象,而不是一个列表。
语法:将列表生成式的 [] 替换为 () 即可
1 | # 列表生成式 |