我们知道,函数体包含 yield 关键字的函数不是一个普通函数。这种函数叫做 生成器 ( generator ),一般用于循环处理结构,应用得当可以极大优化内存使用效率。例如,设计一个函数,打开文件并将每一行转成大写并返回:
def read_file_upper(path):
lines = []
with open(path) as f:
for line in f:
lines.append(line.upper())
return lines
这个版本的函数,在内部创建了一个 list 对象,用于保存转换结果。for 循环则遍历文件每一行,将其转成大写并追加到列表中。这样一来,文件中的每一行均需要保存在列表中,如果文件很大,内存开销可想而知。
我们可以借助 yield 关键字,将 read_file_upper 函数改成生成器版本。函数主体逻辑没有任何变化,只是将每行数据的处理结果通过 yield 逐个返回,而不是收集到 list 对象后再返还。
def iter_file_upper(path):
with open(path) as f:
for line in f:
yield line.upper()
如果现在有一个文本文件 data.txt ,里面包含以下内容:
hello, world
life is short, use python
my wechat id is: coding-fan
bye
用 iter_file_upper 生成器,我们可以这样对它进行处理:
>>> for line in iter_file_upper('text.txt'):
… print(line.strip())
HELLO, WORLD
LIFE IS SHORT, USE PYTHON
MY WECHAT ID IS: CODING-FAN
BYE
iter_file_upper 生成器用法与 read_file_upper 函数大致相同,但它不会一次性拿住文件所有数据行,而是逐行处理、逐个返回,这样便将内存使用量降到最低。