【Python】yield关键字的使用与实现
·
yield 是 Python 中一个非常重要的关键字,它用于创建生成器函数。生成器函数可以暂停和恢复执行,使得它们能够高效地处理大数据集或无限序列。
基础概念
- 生成器函数 vs 普通函数
# 普通函数
def normal_function(n):
result = []
for i in range(n):
result.append(i * i)
return result
# 生成器函数
def generator_function(n):
for i in range(n):
yield i * i
# 使用普通函数
print("普通函数结果:", normal_function(5)) # [0, 1, 4, 9, 16]
# 使用生成器函数
gen = generator_function(5)
print("生成器结果:", list(gen)) # [0, 1, 4, 9, 16]
- yield 的工作原理
def simple_generator():
print("开始执行")
yield 1
print("继续执行")
yield 2
print("结束执行")
# 创建生成器对象
gen = simple_generator()
# 第一次调用 next()
print("第一次调用:")
value1 = next(gen) # 输出: 开始执行
print(f"得到值: {value1}") # 得到值: 1
# 第二次调用 next()
print("第二次调用:")
value2 = next(gen) # 输出: 继续执行
print(f"得到值: {value2}") # 得到值: 2
# 第三次调用 next() 会抛出 StopIteration 异常
try:
value3 = next(gen) # 输出: 结束执行
except StopIteration:
print("生成器已耗尽")
实际应用示例
- 读取大文件
def read_large_file(file_path):
"""逐行读取大文件,避免内存溢出"""
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
yield line.strip()
# 使用示例
for line in read_large_file('large_file.txt'):
# 处理每一行数据
print(line)
# 不需要一次性加载整个文件到内存
- 生成无限序列
def fibonacci():
"""生成斐波那契数列"""
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 使用示例
fib_gen = fibonacci()
for i in range(10):
print(next(fib_gen)) # 输出前10个斐波那契数
- 管道数据处理
def numbers(n):
for i in range(n):
yield i
def square(nums):
for num in nums:
yield num ** 2
def filter_even(nums):
for num in nums:
if num % 2 == 0:
yield num
# 构建数据处理管道
result = filter_even(square(numbers(10)))
print(list(result)) # [0, 4, 16, 36, 64]
高级用法
- 使用 send() 方法与生成器交互
def interactive_generator():
value = 0
while True:
# yield 可以接收外部发送的值
received = yield value
if received is not None:
value = received
else:
value += 1
gen = interactive_generator()
print(next(gen)) # 0
print(gen.send(10)) # 10
print(next(gen)) # 11
print(next(gen)) # 12
- 使用 yield from 委托生成器
def sub_generator():
yield from range(3)
yield from ['a', 'b', 'c']
def main_generator():
yield "开始"
yield from sub_generator()
yield "结束"
for item in main_generator():
print(item)
# 输出: 开始, 0, 1, 2, a, b, c, 结束
- 协程实现
def coroutine():
while True:
received = yield
print(f"收到: {received}")
# 创建协程
co = coroutine()
next(co) # 启动协程
co.send("Hello") # 收到: Hello
co.send("World") # 收到: World
实现原理模拟
为了更好地理解 yield 的工作原理,我们可以模拟一个简单的生成器:
class SimpleGenerator:
"""模拟生成器行为的类"""
def __init__(self, n):
self.n = n
self.current = 0
self.state = "created"
def __iter__(self):
return self
def __next__(self):
if self.state == "finished":
raise StopIteration
if self.current < self.n:
result = self.current ** 2
self.current += 1
return result
else:
self.state = "finished"
raise StopIteration
# 使用模拟的生成器
fake_gen = SimpleGenerator(5)
for value in fake_gen:
print(value) # 输出: 0, 1, 4, 9, 16
性能对比
import time
import sys
def regular_list(n):
result = []
for i in range(n):
result.append(i * i)
return result
def generator_version(n):
for i in range(n):
yield i * i
# 内存使用对比
n = 1000000
# 列表版本
start = time.time()
list_result = regular_list(n)
list_memory = sys.getsizeof(list_result)
list_time = time.time() - start
# 生成器版本
start = time.time()
gen_result = generator_version(n)
gen_memory = sys.getsizeof(gen_result)
gen_time = time.time() - start
print(f"列表版本 - 时间: {list_time:.4f}s, 内存: {list_memory} 字节")
print(f"生成器版本 - 时间: {gen_time:.4f}s, 内存: {gen_memory} 字节")
总结
yield 关键字是 Python 中实现生成器的核心,它提供了:
- 内存效率:按需生成值,避免一次性加载所有数据到内存
- 惰性求值:只在需要时计算值
- 状态保持:函数执行状态在 yield 之间保持
- 代码简洁:使用简洁的语法实现复杂的迭代逻辑
生成器是 Python 中处理大数据集、实现协程和构建数据处理管道的强大工具。
更多推荐


所有评论(0)