Python yield 最通俗、最实用的讲解
yield是 Python 中一个非常强大的关键字,它用于创建生成器(Generator)。理解yield对于编写高效、节省内存的迭代代码至关重要。
一句话记住
yield = 让函数变成 “生成器”,可以暂停执行、分段返回数据,不占满内存。
你可以把它理解成:可以暂停 / 继续的 return。
yield 是 Python 的关键字,用于创建生成器(Generator) 核心特性: 1. **暂停执行** - 函数执行到 yield 时暂停,返回值给调用者 2. **恢复执行** - 下次调用时从 yield 之后继续执行 3. **状态保持** - 函数的局部变量和执行状态都会被保留 4. **惰性计算** - 按需生成值,节省内存 yield vs return: - return: 函数执行结束,返回一个值,函数退出 - yield: 函数暂停,返回一个值,函数可以继续执行
1.最直观对比:return vs yield
1.1. return(普通函数)
- 运行 → 返回结果 →直接结束
- 一次性返回所有数据,数据多了占内存
def func(): return 1 return 2 # 永远不会执行1.2. yield(生成器函数)
- 运行 → 遇到 yield →暂停,返回值
- 下次调用 →从暂停处继续执行
- 可以多次返回,不占内存
def gen(): yield 1 # 暂停,返回1 yield 2 # 下次继续,返回2 yield 31.3. yield 的工作原理
惰性求值
yield实现了惰性求值(Lazy Evaluation):只在需要时才计算下一个值。
2. yield 最核心 4 大用途(实战必用)
2.1. 处理超大数据 / 无限数据(不爆内存)
这是 yield最重要的用途!
比如你要生成 1 亿个数:
- 用 list 会直接卡死(内存装不下)
- 用 yield 几乎不占内存
# 生成器:一次只生成一个数,用完再生成下一个 def count(): n = 0 while True: yield n n += 1适用场景:读取超大文件、爬取无限分页数据、处理千万级日志。
2.2. 分段执行(前后置代码)
就是你刚才学的pytest fixture!https://blog.csdn.net/Kingairy/article/details/161514387
@pytest.fixture def open_browser(): print("打开浏览器") # 前置 yield driver # 暂停,返回给测试用例 print("关闭浏览器") # 用例跑完后执行(后置)yield 在这里的作用:
- 先执行前面代码
- 暂停,把值给测试用例
- 用例结束后,自动执行后面的清理代码
2.3. 协程 / 异步任务(高级)
yield可以让函数暂停执行,去做别的事,再回来继续。 这是 Python 异步编程的基础。
2.4. 流式处理数据(管道模式)
# 读超大文件,一次只读一行,不占内存 def read_large_file(file): with open(file) as f: for line in f: yield line2.5. 无限序列
def infinite_sequence(): """生成无限序列""" num = 0 while True: yield num num += 1 # 使用 for i in infinite_sequence(): if i > 100: break print(i)3.yield 的高级特性
3.1. send() - 向生成器发送值
def gen(): # 重点:yield 左边可以接收 send 进来的值 value = yield "开始" print("生成器收到:", value) value2 = yield "第二步" print("生成器又收到:", value2) yield "结束" # 创建生成器 g = gen() # 第一次必须 next() 或 send(None) print(next(g)) # 输出:开始 # 往生成器里传数据 print(g.send("我是数据1")) # 输出:第二步 print(g.send("我是数据2")) # 输出:结束3.2. throw() - 向生成器抛出异常
def generator(): try: yield 1 yield 2 except ValueError: yield '处理异常' yield 3 gen = generator() print(next(gen)) # 1 print(gen.throw(ValueError)) # 处理异常 print(next(gen)) # 33.3. close() - 关闭生成器
def generator(): try: yield 1 yield 2 finally: print("生成器被关闭") gen = generator() print(next(gen)) # 1 gen.close() # 生成器被关闭3.4. yield from - 委托生成器
def sub_generator(): yield 1 yield 2 yield 3 def main_generator(): # 使用 yield from 委托给子生成器 yield from sub_generator() yield 4 yield 5 for value in main_generator(): print(value) # 1, 2, 3, 4, 54.超简记忆口诀
- return:返回,结束,一次性,占内存
- yield:暂停,继续,多次返回,不占内存
- ** pytest 里 **:用来做前后置(setup/teardown)
总结
- yield 让函数变成生成器,支持暂停 / 继续
- 最大优势:处理大数据不爆内存
- 你现在最常用:pytest fixture 做前后置准备 + 清理
- 本质:分段执行函数
