在python中,yield是一个关键字,用于定义生成器函数(generator function),它的作用是在函数执行过程中暂停函数,并返回一个中间值,此后可以从暂停的地方继续执行,而不是一次性运行整个函数,也不必用return关键字来返回结果。yield用于让一个函数变为生成器(generator),调用一个带有yield关键字的函数时,不会立即执行函数体,而是会返回一个生成器对象。每次从生成器对象中请求一个值(例如通过next()或循环)时,函数会从上一次yield的地方恢复执行,并生成一个yield的值,接着再次暂停,直到函数执行完毕或者遇到函数中的return语句,迭代才会结束,通常此时抛出StopIteration异常(在for循环中可忽略)。 | | |
|---|
| | 函数执行到 yield 时,暂停并返回一个值,下次继续执行 |
| | 每次 yield 后保持函数的执行状态(局部变量不会销毁) |
| | |
| | |
def simple_generator(): yield 1 yield 2 yield 3# 调用生成器函数,不会执行函数体,而是返回生成器对象gen = simple_generator()# 通过next()手动获取 yield 的值print(next(gen)) # 输出:1print(next(gen)) # 输出:2print(next(gen)) # 输出:3# print(next(gen)) # 如果再调用,会抛出 StopIteration 异常
def count_to_three(): yield 1 yield 2 yield 3for num in count_to_three(): print(num)# 输出:# 1# 2# 3
说明:for循环内部会自动处理StopIteration,无需手动调用next()当要生成大批量的序列号(几百万个),但不想一次存入内存,就可以用生成器+yielddef generate_serial_numbers(n): i = 0 while i < n: yield i i += 1# 只在使用时逐个生成,不会一次性生成所有数字for num in generate_serial_numbers(5): print(num)# 输出:0 1 2 3 4
python的迭代器协议要求实现__iter__() 和 __next__(),而使用生成器函数+yield可以非常简洁的实现生成器功能。如读取大文件,处理数据流时,可以一行一行的处理,而不是一次性读取全部内容def read_large_file(file_path): with open(file_path, 'r', encoding='utf-8') as f: for line in f: yield line.strip() # 去掉换行符for line in read_large_from_file(): print(line)
1. yield可以返回多个值(实际上返回的是一个对象,通常是元组)def generate_points(): yield (1, 2) yield (3, 4) yield (5, 6)for x, y in generate_points(): print(f"x={x}, y={y}")
语法:(expression for item in iterable)
类似列表推导式,但返回生成器。
# 生成器表达式(不会立即计算)gen_exp = (x * 2 for x in range(5))for val in gen_exp: print(val)# 输出:0 2 4 6 8
说明:生成器表达式更节省内存,适用于大数据处理
生成器函数中除了使用yield value 语句返回值之外,还可以通过value = yield语句接收外部传入的数据,用send()方法来发送数据。def interactive_generator(): print("开始...") x = yield "请发送一个数字" # 第一次yield返回提示,暂停,等待send() print(f"你发送了: {x}") yield f"你发送的数字是 {x}"gen = interactive_generator()# 第一步:启动生成器,获取第一个 yield 的值msg = next(gen) # 或 gen.send(None)print(msg) # 输出:请发送一个数字# 第二步:向生成器发送一个值response = gen.send(42) # 发送数字 42print(response) # 输出:你发送的数字是 42
注意:第一次启动生成器必须用 next(gen) 或 gen.send(None),不能直接 send 值yield from 用于在一个生成器中委托给另一个生成器或可迭代对象,用于减少嵌套生成器的代码。def sub_generator(): yield "a" yield "b"def main_generator(): yield "开始" yield from sub_generator() # 委托给 sub_generator yield "结束"for item in main_generator(): print(item)# 输出:# 开始# a# b# 结束
注意:yield from 常用于编写更清晰、模块化的生成器代码,也用于实现异步编程中的协程(如 asyncio)通俗的理解,yield 就像你在讲故事时,讲到一半停下来,听的人说“继续”,你再接着讲。每次你讲一段,就yield 一个内容,然后等对方让你继续。整个故事可以很长,但你不需要一次讲完。