生成器通过yield实现惰性计算,调用时返回生成器对象,迭代时逐个生成值并暂停执行,保留状态,按需计算,减少内存占用。

Python中的
yield
yield
yield
for
next()
yield
yield
下一次迭代时,函数会从上次
yield
yield
return
StopIteration
这种机制的巨大优势在于内存管理。常规函数如果需要返回一个大的列表或序列,它会一次性在内存中构建出整个序列。而生成器则是一个一个地生成元素,每次只在内存中保留当前正在处理的元素的状态,极大地减少了内存占用,特别适用于处理文件、网络流或者无限序列等场景。
立即学习“Python免费学习笔记(深入)”;
def simple_generator():
print("开始生成...")
yield 1
print("生成了1,继续...")
yield 2
print("生成了2,即将结束...")
yield 3
print("生成完毕。")
# 调用生成器函数,得到一个生成器对象
gen = simple_generator()
# 第一次next()调用
print(next(gen))
# 第二次next()调用
print(next(gen))
# 第三次next()调用
print(next(gen))
# 尝试第四次next()调用会抛出StopIteration
# print(next(gen))生成器实现惰性计算和内存优化的秘密,在于其独特的“暂停与恢复”机制。当一个函数中包含
yield
每次我们请求生成器提供下一个值(通过
next()
for
yield
yield
yield
考虑一个处理大型日志文件的例子。如果我们需要筛选出文件中所有包含特定关键词的行:
def read_large_log_file(filepath, keyword):
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
if keyword in line:
yield line.strip() # 找到一行就返回,而不是等待整个文件处理完
# 假设有一个非常大的日志文件 'server.log'
# log_lines = list(read_large_log_file('server.log', 'ERROR')) # 这种方式会一次性加载所有匹配行到内存
# 更好的方式是直接迭代:
for error_line in read_large_log_file('server.log', 'ERROR'):
print(f"发现错误: {error_line}")
# 这里可以对每一行进行进一步处理,而不需要将所有错误行都存入内存在这个例子中,
read_large_log_file
yield
yield from
yield from
yield
yield from
yield
yield
yield
yield from
yield from
send()
throw()
close()
yield
我们来看一个例子:
def sub_generator(start, end):
for i in range(start, end):
yield i
def main_generator():
print("开始主生成器")
# 使用 yield 逐个委托
# for value in sub_generator(1, 3):
# yield value
# for value in sub_generator(10, 12):
# yield value
# 使用 yield from 委托
yield from sub_generator(1, 3)
print("子生成器1完成")
yield from sub_generator(10, 12)
print("子生成器2完成")
yield 99 # 主生成器自己的值
print("主生成器结束")
# 迭代主生成器
for item in main_generator():
print(f"从主生成器得到: {item}")在这个例子中,
main_generator
sub_generator
yield
for
yield
yield from
sub_generator
yield
return
生成器和
yield
yield
处理大型文件或数据流: 这是最典型的应用场景。当文件内容(如日志文件、CSV 文件、JSON Lines 文件)过大,无法一次性加载到内存时,生成器可以逐行或逐块读取并处理,显著减少内存占用。例如,一个Web服务器的访问日志文件可能达到GB级别,使用生成器逐行解析,可以避免内存溢出。
def parse_large_csv(filepath):
with open(filepath, 'r', encoding='utf-8') as f:
header = next(f).strip().split(',') # 读取标题行
for line in f:
values = line.strip().split(',')
# 假设每行数据与标题对应
yield dict(zip(header, values))
# 遍历大型CSV文件,逐条处理数据
# for row_data in parse_large_csv('large_data.csv'):
# process_data_record(row_data)生成无限序列或大数据集: 某些序列在逻辑上是无限的(如斐波那契数列、素数序列),或者数据集非常庞大,预先生成所有数据不切实际。生成器可以按需生成这些值,避免了内存限制。
def fibonacci_sequence():
a, b = 0, 1
while True: # 无限生成
yield a
a, b = b, a + b
# for _ in range(10):
# print(next(fibonacci_sequence())) # 每次取一个斐波那契数构建数据处理管道(Pipelines): 在数据分析或ETL(提取、转换、加载)过程中,数据往往需要经过一系列的转换。生成器可以很自然地构建这种管道,一个生成器的输出作为下一个生成器的输入,形成一个高效、惰性求值的链条。每个阶段只处理它当前需要的数据,而不是将所有中间结果都存储起来。
自定义迭代器: 当你需要实现一个自定义的、可迭代的数据结构时,使用生成器函数通常比手动编写一个带有
__iter__
__next__
异步编程的早期模式(协程): 在
async/await
yield
yield from
async/await
yield
内存敏感型应用: 任何对内存使用有严格要求的应用,例如嵌入式系统、大数据处理的边缘节点,或者需要同时运行大量任务的服务器端应用,生成器都是一个强大的工具。
选择
yield
以上就是python中的yield是什么_python yield关键字与生成器工作原理解析的详细内容,更多请关注php中文网其它相关文章!
python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号