Python 生成器实践
1. 遍历文本文件中的单词
假设存在文本文件 test.txt,内容如下:
The Zen of Python Beautiful is better than ugly Simple is better than complex
注意文件包含有空行,要求完成如下任务:
统计文件有多少个单词
统计文件中每个单词出现的频率
2. 直接遍历的方法
请参考词条 “Python 中的迭代器趣味实践” 的第 2 小节,通过直接遍历文件中单词的方式实现 “统计单词的个数” 和 “统计单词的出现频率”。
2.1 优点
直接遍历的方式的优点在于代码简单,框架代码如下:
file = open('test.txt')while True:line = file.readline()if not line:breakwords = line.split() for word in words:处理 word
在第 4 行,读取文件的每一行
在第 8 行,将文件的一行分割为多个单词
在第 10 行,对当前正在遍历的单词进行处理
2.2 缺点
直接遍历的方式的缺点在于代码重复,实现 “统计单词个数” 和 “统计单词出现频率” 这两个功能需求时,遍历单词的框架代码是重复的。
3. 基于迭代器的方法
请参考词条 “Python 中的迭代器趣味实践” 的第 3 小节和第 4 小节,通过基于迭代器的方式实现 “统计单词的个数” 和 “统计单词的出现频率”。
3.1 优点
使用迭代器的方式的优点在于遍历单词的代码简单,使用如下代码:
for word in IterateWord(file):处理 word
即可对文件中所有的单词进行遍历。
3.2 缺点
使用迭代器的方式的缺点在于迭代器的实现较为复杂,相比之下,直接遍历的框架代码则非常简单直观。在下面的小节中,我们基于生成器简化迭代器的实现。
4. 基于生成器的方法
4.1 实现生成器
本小节使用生成器实现遍历文件中所有的单词,代码如下:
def generateWord(file):while True:line = file.readline()if not line:breakwords = line.split() for word in words:yield word
在第 1 行,定义生成器函数 generateWord,遍历文件 file 中的单词
在第 3 行,读取文件的一行
在第 4 行,如果 not line 为真,则表示读取文件结束,使用 break 退出
在第 7 行,把 line 切割为多个单词
在第 8 行,遍历列表 words
在第 9 行,使用 yield 关键字返回当前正在遍历的单词
4.2 统计单词的个数
file = open('test.txt')count = for word in generateWord(file):print(word)count = count +
在第 1 行,打开文件 test.txt
在第 2 行,变量 count 用于记录文件中单词的个数
在第 4 行,遍历文件中的每一个单词
在第 5 行,打印当前遍历的单词
在第 6 行,统计单词个数
程序运行输出结果如下:
The Zen of Python Beautiful is better than ugly Simple is better than complex count = 14
4.3 统计单词的出现频率
file = open('test.txt')dict = {}for word in generateWord(file):if word in dict:dict[word] += else:dict[word] = for word,count in dict.items():print('%s: %d' % (word, count))
在第 1 行,打开文件 test.txt,变量 file 标识已经打开的文件
在第 4 行,遍历每一行文本的单词
则在第 8 行,该单词出现的次数初始化为 1
则在第 5 行,该单词出现的次数加 1
在第 5 行,如果 word 已经存在于 dict 中
在第 7 行,如果 word 不存在于 dict 中
在第 10 行,打印 dict 的键和值
程序运行输出结果如下:
The: 1 Zen: 1 of: 1 Python: 1 Beautiful: 1 is: 2 better: 2 than: 2 ugly: 1 Simple: 1 complex: 1
结果表明:
单词 is better than 出现了 2 次
其它单词出现了 1 次
4.4 总结
与 “直接遍历” 和 “通过迭代器遍历” 这两种方式相比,基于生成器的方法由如下优点:
4.4.1 实现生成器简单
实现生成器的函数 generateWord 的逻辑简单直观,代码如下:
def generateWord(file):while True:line = file.readline()if not line:breakwords = line.split() for word in words:yield word
首先,函数依次读取文件的每一行
然后,再把读取的行切割成单词
最后,遍历单词
4.4.2 使用生成器简单
通过 for 循环即可遍历文件中的单词,generateWord 隐藏了各种实现细节,代码如下:
for word in generateWord(file):处理 word