有勇气的牛排博客

Python 生成器 Genrator yield的使用

有勇气的牛排 637 Python 2024-08-21 22:35:21

进群口令:博客

1 前言

1.1 定义

  • 生成器是一种特殊的迭代器,用 yield 语句或 生成器表达式 创建。
  • 不需要手写 __iter__()__nex__(),Python会自动实现迭代器协议。
  • yield 会保存函数的执行状态,并在下次迭代时从该位置继续。

yield是一个关键字,可以暂停函数执行(函数挂起),并返回序列值,等被执行到的时候才会取出数据,特别大数据(节省内存)和流式场景。当使用next()、send()函数,即可以从断点处继续执行。

1.2 特点

  1. 语法简洁:无需类结构即可生成迭代器。
  2. 惰性求值:按需生成内存,节省内存。
  3. 可以无限生成:比如斐波那契数列、自然序列。

2 基本案例

2.1 生成器函数

案例1

# -*- coding: utf-8 -*- def my_generator(): yield 1 yield 2 yield 3 gen = my_generator() for value in gen: print(value) # 输出:1 2 3

案例二

def my_generator(): for i in range(5): yield i gen = my_generator() print(next(gen)) # 0 print(next(gen)) # 1

yield 生成器函数

2.2 带状态的生成器/状态保留

# -*- coding: utf-8 -*- def countdown(n): while n > 0: yield n n -= 1 for num in countdown(5): print(num, end=" ") # 输出:5 4 3 2 1

2.3 生成器表达式

# -*- coding: utf-8 -*- gen_exp = (x * x for x in range(5)) print(next(gen_exp)) # 0 print(next(gen_exp)) # 1 print(next(gen_exp)) # 4 print(next(gen_exp)) # 9 print(next(gen_exp)) # 16 print(next(gen_exp)) # StopIteration

节省内存

案例作用: 循环输出 0 - limit 的数值

常规思路:提前生成放到列表中,或使用range

yield优点:直到执行到的时候,才计算具体值,完全不需要提前计算好值,即可以节省内存。

def generate_numbers(limit): num = 0 while num < limit: yield num num += 1 for num in generate_numbers(1000): print(num) # 逐个生成并输出数字

yield节省内存

3 高级用法 send()

允许外部传入数据

send(value) 可以在生成器暂停时,向其发送一个值。

# -*- coding: utf-8 -*- def echo(): while True: val = yield print('echo:', val) g = echo() next(g) # 先启动生成器 g.send('你好:有勇气的牛排')

4 常见场景

  • 大文件处理。
  • 数据管道(pipeline)中分步生成数据。
  • 无限数列生成(斐波那契、自然数、质数)
  • 协程基础(早起 Python 协程基于生成器实现)

5 迭代器与生成器的区别

对比项 迭代器(Iterator) 生成器(Generator)
创建方式 类+ __iter__&__next__ yield / 生成器表达式
可读性 相对繁琐 简洁
协议实现 需要手写 自动实现
惰性求值
内存占用 更小(天然按需生成)
使用复杂度

总结:

在 Python 中,迭代器是实现了 __iter__()__next__ 方法的对象,支持惰性求值,可以节省内存。

生成器是迭代器的一种特殊实现,可以用 yield 或生成器表达式创建,语法更简洁,自动保存执行状态,适合处理大数据流火无限序列。

它们共同点是支持按需生成,不同点是生成器更易用、可读性更高。

评论区

×
×