Python
基础语法
01概念
02安装
03变量
04字符串
05数
06常量与注释
07列表
08元组
09if语句
10字典
11集合
12复合数据类型对比
13推导式
14用户输入
15while循环
16函数
17类
18面向对象编程
19文件操作
20异常处理
21日期和时间
22魔术方法
23内置函数
24线程
25并发&并行
26正则表达式
27迭代器
28装饰器
29生成器
30上下文管理器
31函数式编程
32闭包
33解包
34工具库
35连接关系型数据库
36虚拟环境
37异步编程
网络爬虫
01urllib库[了解]
02requests库
03数据交换格式
04解析库
05lxml
06Beautiful Soup
07Xpath语法
08动态网页的处理
-
+
首页
29生成器
在 Python 中,生成器(Generator)是一种特殊的迭代器,它通过**简洁的语法**实现了迭代器协议,无需手动定义\_\_iter\_\_()和\_\_next\_\_()方法。生成器的核心价值在于**惰性计算**(Lazy Evaluation)—— 只在需要时生成下一个元素,而非一次性创建所有元素,这使得它在处理大数据集、无限序列或流式数据时极具优势。 ## 特征 **惰性计算**:按需生成值,不一次性产生所有结果 **内存高效**:不需要存储整个序列在内存中 **状态保持**:自动保存执行状态(局部变量、指令指针等) **一次性使用**:生成器只能迭代一次 ## 生成器函数 生成器(Generator) 使用 yield 语句而不是 return 来返回值,生**成器函数在每次调用 yield 时会暂停执行并保存当前状态,下次请求值时从暂停的地方继续执行。** 生成器函数是最常用的生成器形式,通过yield关键字替代return返回元素,实现 “暂停 - 恢复” 的迭代逻辑。 **基本语法:** - 生成器函数定义:函数体中包含yield关键字(可多个)。 - 调用生成器函数:返回**生成器对象**(而非函数执行结果),函数体不会立即执行。 - 迭代过程:每次调用next()(或在for循环中),函数体执行到yield处暂停,返回yield后的值;再次调用时,从暂停处继续执行,直到函数结束(自动抛出StopIteration)。 ```python def simple_generator(): print("开始执行") yield 1 # 第一次调用next()时返回1,暂停 print("继续执行") yield 2 # 第二次调用next()时返回2,暂停 print("执行结束") # 第三次调用next()时,函数结束,抛出StopIteration # 调用生成器函数:返回生成器对象(函数体未执行) gen = simple_generator() print(type(gen)) # <class 'generator'>(生成器是特殊的迭代器) # 第一次迭代:执行到第一个yield print(next(gen)) # 输出:开始执行 → 1 # 第二次迭代:从上次暂停处继续,执行到第二个yield print(next(gen)) # 输出:继续执行 → 2 # 第三次迭代:函数体执行完毕,抛出StopIteration try: next(gen) except StopIteration: print("迭代结束") # 输出:执行结束 → 迭代结束 ``` 输出结果: ```python <class 'generator'> 开始执行 1 继续执行 2 执行结束 迭代结束 ``` **yield与return的核心区别** | 特性 | yield | return | | ------------ | ------------------------------------ | ------------------------------------ | | 作用 | 返回一个值,并暂停函数执行 | 返回一个值,并**终止**函数执行 | | 调用次数 | 可在函数中多次使用(每次返回一个值) | 函数中最多执行一次(执行后函数结束) | | 与迭代的关系 | 用于生成迭代器的元素 | 用于结束函数,不参与迭代逻辑 | ```python # 生成器函数(yield):可返回多个值 def yield_numbers(): yield 1 yield 2 yield 3 # 普通函数(return):只能返回一次 def return_numbers(): return 1 return 2 # 永远不会执行 print(list(yield_numbers())) # [1, 2, 3](多次返回) print(return_numbers()) # 1(仅返回一次) ``` 输出结果: ```python [1, 2, 3] 1 ``` **生成器函数的状态保存** 生成器函数内部会自动保存迭代状态(如变量值、执行位置),每次next()调用都会从上次暂停的位置继续,无需手动维护状态。这是生成器比手动实现迭代器更简洁的核心原因。 ```python def fibonacci(n): a, b = 0, 1 # 初始状态 count = 0 while count < n: yield b # 返回当前斐波那契数,暂停 a, b = b, a + b # 更新状态 count += 1 # 生成前5个斐波那契数 fib = fibonacci(5) for num in fib: print(num) # 输出:1 1 2 3 5 ``` 输出结果: ```python 1 1 2 3 5 ``` ## 生成器表达式 生成器表达式是列表推导式的 “惰性版本”,语法类似列表推导式,但用**圆括号()** 包裹,返回生成器对象而非列表。 语法:(expression for item in iterable if condition) 特点: - 惰性计算:不立即生成所有元素,仅在迭代时生成。 - 内存高效:相比列表推导式,不占用大量内存(尤其处理大数据时)。 - 一次性迭代:与生成器函数一样,迭代结束后无法重置。 ```python # 列表推导式:一次性生成所有元素,占用内存 list_comp = [x*2 for x in range(1000000)] print(type(list_comp)) # <class 'list'> print(len(list_comp)) # 1000000(已生成所有元素) # 生成器表达式:仅返回生成器,不占用内存 gen_expr = (x*2 for x in range(1000000)) print(type(gen_expr)) # <class 'generator'> # print(len(gen_expr)) # 报错:生成器没有长度(元素未生成) # 迭代生成器表达式(按需生成元素) for _ in range(3): print(next(gen_expr)) # 输出:0 2 4 ``` 输出结果: ```python <class 'list'> 1000000 <class 'generator'> 0 2 4 ``` **适用场景**:生成器表达式适合**简单的生成逻辑**,可替代列表推导式处理大数据,或作为函数参数(避免创建临时列表)。 ## 核心方法 生成器作为特殊的迭代器,除了__next__(),还支持三个特殊方法,用于更灵活地控制迭代过程。 **1. send(value):向生成器发送值** 功能:向生成器发送一个值,作为yield表达式的返回值,并触发下一次迭代(等效于next(),但可传递参数)。 注意:第一次调用send()时必须传入None(因为生成器尚未在yield处暂停)。 ```python def counter(): count = 0 while True: # yield表达式的返回值由send()传入 reset = yield count # 第一次迭代时,yield返回count=0,暂停 if reset: count = 0 # 若send(True),则重置计数器 else: count += 1 c = counter() print(c.send(None)) # 第一次必须传None → 0(等价于next(c)) print(c.send(False)) # 发送False,不重置 → 1 print(c.send(False)) # 继续累加 → 2 print(c.send(True)) # 发送True,重置 → 0 print(c.send(False)) # 从0开始累加 → 1 ``` 输出结果: ```python 0 1 2 0 1 ``` **2. throw(type, value=None, traceback=None):向生成器抛出异常** 功能:在生成器暂停处抛出指定异常,可用于终止迭代或处理错误。 ```python def my_generator(): try: yield 1 yield 2 yield 3 except ValueError: print("捕获到ValueError,终止迭代") gen = my_generator() print(next(gen)) # 1 gen.throw(ValueError) # 在第二个yield前抛出异常 → 输出:捕获到ValueError,终止迭代 try: next(gen) # 生成器已终止,抛出StopIteration except StopIteration: print("迭代结束") ``` 输出结果: ```python 1 捕获到ValueError,终止迭代 ``` **3. close():关闭生成器** 功能:手动关闭生成器,后续调用next()会直接抛出StopIteration。 ```python def numbers(): yield 1 yield 2 yield 3 gen = numbers() print(next(gen)) # 1 gen.close() # 关闭生成器 try: next(gen) # 已关闭,抛出StopIteration except StopIteration: print("生成器已关闭") ``` 输出结果: ```python 1 生成器已关闭 ``` ## 应用场景 **1. 处理大型数据集或文件** 当数据量超过内存限制时(如 10GB 日志文件),生成器可逐行 / 逐块处理数据,避免内存溢出。 **2. 生成无限序列** 生成器可表示无限序列(如自然数、随机数),因为它不需要存储所有元素,只需按需生成下一个。 **3. 实现轻量级协程(协作式多任务)** 通过yield和send(),生成器可实现简单的协程(Coroutine),在单线程中模拟多任务切换。 **4. 管道式数据处理(流式计算)** 多个生成器可串联成 “管道”,前一个生成器的输出作为后一个的输入,实现高效的流式数据处理(类似 Unix 管道)。 ## 对比 | 类型 | 本质 | 内存占用 | 随机访问 | 一次性迭代 | 适用场景 | | ------ | ---------------------------------- | ---------------- | -------- | ---------- | -------------------------- | | 生成器 | 特殊的迭代器(自动实现协议) | 极低(惰性生成) | 不支持 | 是 | 大数据、无限序列、流式处理 | | 迭代器 | 手动实现_\\_iter\_\_和\_\_next\_\_ | 低(按需生成) | 不支持 | 是 | 自定义迭代逻辑 | | 列表 | 容器(存储所有元素) | 高(全部加载) | 支持 | 否 | 小数据、需要随机访问的场景 |
毛林
2025年9月7日 11:45
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码