这篇文章将从头到尾围绕一个核心问题展开:
在 Python 中,有哪些函数或模块中的函数是用生成器实现的?它们如何体现“生成器”的特点?
我们将明确区分:
-
✅ 真正使用了
yield或生成器表达式(generator expression)的函数; -
❌ 不包括普通的可迭代对象、迭代器对象(如
map,filter,zip,range等);
一、先来回顾:生成器的本质是什么?
✅ 定义:
生成器是一种特殊的函数,它通过 yield 返回值,并能在多次调用之间保持状态。
你可以通过两种方式创建生成器:
-
生成器函数:包含
yield的函数; -
生成器表达式:类似列表推导式,但使用
()而非[]。
# 生成器函数
def my_gen():
yield 1
yield 2
yield 3
# 生成器表达式
gen = (x * x for x in range(5))
📌 这两个才是真正的“生成器对象”。
二、哪些 Python 内置/标准库函数是用生成器实现的?
虽然 Python 很多函数返回的是“惰性求值的迭代器”,但真正以生成器方式实现的函数并不多。以下是几个典型例子:
✅ 示例1:os.walk()
import os
for root, dirs, files in os.walk('.'):
print(root)
-
os.walk()是一个生成器函数,它递归地遍历目录树; -
每次调用
next(),返回下一级目录的信息; -
它内部使用了
yield来逐层生成结果。
🔍 查看源码你会发现它大致结构如下:
def walk(top):
yield (top, list_of_dirs, list_of_files)
for dir in list_of_dirs:
yield from walk(os.path.join(top, dir))
📌 所以它是真正的生成器!
✅ 示例2:tokenize.generate_tokens()
import tokenize
from io import BytesIO
code = b"x = 1 + 2"
tokens = tokenize.generate_tokens(BytesIO(code).readline)
for token in tokens:
print(token)
-
generate_tokens()是一个生成器函数,用于逐个读取 Python 源代码中的 token; -
它通过
yield返回每个 token; -
非常适合处理大文件或流式输入。
✅ 示例3:itertools 中部分函数的实现依赖生成器
虽然 itertools 函数返回的是迭代器对象,但很多底层实现是用生成器完成的。
比如 itertools.count()、itertools.cycle()、itertools.repeat() 等函数,在 CPython 实现中是用生成器逻辑模拟的。
虽然从用户角度看它们不是生成器对象,但从实现角度看,它们的行为和生成器一致。
三、常见误解澄清:这些不是生成器!
| 函数 | 类型 | 是否是生成器 |
|---|---|---|
map() | 迭代器 | ❌ |
filter() | 迭代器 | ❌ |
zip() | 迭代器 | ❌ |
range() | 序列类型 | ❌ |
open() 行迭代 | 文件迭代器 | ❌ |
列表推导式 [x*x for x in ...] | 列表 | ❌ |
生成器表达式 (x*x for x in ...) | 生成器表达式 | ✅ |
📌 特别注意:
-
生成器表达式虽然名字里有“生成器”,但它是一个表达式,最终产生的是一个生成器对象;
-
而
map,filter等只是惰性迭代器,不是生成器对象。
四、实战技巧:如何判断一个函数是否是生成器?
你可以用以下方法检查一个函数是否是生成器函数:
✅ 方法1:查看函数是否是 types.GeneratorType
import types
def my_gen():
yield 1
print(isinstance(my_gen(), types.GeneratorType)) # True
✅ 方法2:检查函数是否含有 yield
def is_generator_function(func):
return func.__code__.co_flags & 0x20 # CO_GENERATOR 标志位
def my_gen():
yield 1
print(is_generator_function(my_gen)) # True
五、一句话总结
生成器函数必须包含
yield,且调用后返回的是一个生成器对象。在 Python 标准库中,真正用生成器实现的函数不多,但功能强大,如
os.walk()和tokenize.generate_tokens()。
📌 推荐阅读资源:
- 书籍:
-
《流畅的 Python》(Luciano Ramalho)
-
《Python Cookbook》
-
- 工具:
-
Python 官方文档(docs.python.org)
-
- 实战项目:
-
实现一个自己的
walk()函数; -
用生成器构建日志分析系统;
-
使用生成器优化数据流水线处理流程;
-

1714

被折叠的 条评论
为什么被折叠?



