软工作业3:词频统计
一、案例程序分析
1.1、编译环境
pycharm2017、python3.6
1.2、读文件到缓冲区(process_file(dst))
1 def process_file(dst): # 读文件到缓冲区 2 try: # 打开文件 3 f = open(dst, 'r') # dst为文本的目录路径 4 except IOError as s: 5 print(s) 6 return None 7 try: # 读文件到缓冲区 8 bvffer = f.read() 9 except: 10 print('Read File Error!') 11 return None 12 f.close() 13 return bvffer
1.3、处理缓冲区,返回存有词频数据的字典(process_buffer(bvffer))
1 def process_buffer(bvffer): 2 if bvffer: 3 word_freq = {} # 下面添加处理缓冲区 bvffer代码,统计每个单词的频率,存放在字典word_freq 4 for ch in '“‘!;,.?”': # 将文本内容都改为小写且除去文本中的中英文标点符号 5 bvffer = bvffer.lower().replace(ch, " ") 6 words = bvffer.strip().split() 7 # strip()删除空白符(包括'/n', '/r','/t');split()以空格分割字符串 8 for word in words: 9 word_freq[word] = word_freq.get(word, 0) + 1 10 return word_freq
1.4、输出词频前十的单词(output_result(word_freq))
1 def output_result(word_freq): 2 if word_freq: 3 # 根据v[1]即词频数量排序 4 sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True) 5 for item in sorted_word_freq[:10]: # 输出 Top 10 的单词 6 print("词:%-5s 频:%-4d " % (item[0], item[1]))
1.5、主函数对之前的函数进行整合(main())
1 if __name__ == "__main__": 2 dst = 'src/Gone_with_the_wind.txt' # 《飘》文件的路径 3 bvffer = process_file(dst) 4 word_freq = process_buffer(bvffer) 5 output_result(word_freq)
1.6、性能分析
(参考:https://www.cnblogs.com/btchenguang/archive/2012/02/03/2337112.html)
为了方便测试,将原来的运行词频的代码写在main函数中。
1 def main(): 2 dst = 'src/Gone_with_the_wind.txt' # 《飘》文件的路径 3 bvffer = process_file(dst) 4 word_freq = process_buffer(bvffer) 5 output_result(word_freq)
主函数入口改为性能分析的代码。
1 if __name__ == "__main__": 2 cProfile.run("main()", "result") 3 # 把分析结果保存到文件中,不过内容可读性差...需要调用pstats模块分析结果 4 p = pstats.Stats("result") # 创建Stats对象 5 p.strip_dirs().sort_stats("call").print_stats() # 按照调用的次数排序 6 p.strip_dirs().sort_stats("cumulative").print_stats() # 按执行时间次数排序 7 # 根据上面2行代码的结果发现函数process_buffer最耗时间 8 p.print_callees("process_buffer") # 查看process_buffer()函数中调用了哪些函数
二、python代码风格说明
就块注释和行注释而言:“最需要写注释的是代码中那些技巧性的部分. 如果你在下次 代码审查的时候必须解释一下, 那么你应该现在就给它写注释. 对于复杂的操作, 应该在其操作开始前写上若干行注释. 对于不是一目了然的代码, 应在其行尾添加注释.”
# 编译环境:Pycharm2017、Python3.6 # 项目名称:词频统计和性能分析 # 作者:高昶 # 最后修改:2018/9/28 f = open(dst, 'r') # dst为文本的目录路径
三、程序运行命令、运行结果截图
《飘》 文本文件的词频统计运行截图
四、性能分析结果及改进
4.1、总运行时间:
4.2、执行次数最多的部分代码(篇幅有限,截取部分)
即 word_freq[word] = word_freq.get(word, 0) + 1执行的次数最多
1 word_freq[word] = word_freq.get(word, 0) + 1
4.3、执行时间最多的部分代码
4.4、根据4.2和4.3的结果发现函数 process_buffer()耗时占比最大,所以查看process_buffer()函数中 调用了哪些函数
4.5、改进
改进可以从二个方面入手,(1)减少耗时;(2)减少调用次数;但是发现其中调用最多的{method'get' of 'dict' objects}可以理解为是对文本中的词的遍历, 词频算法就是对文本的词遍历,所以该方面不好修改。所以可以从减少耗时入手。
可以将如下代码:
1 for ch in '“‘!;,.?”': # 将文本内容都改为小写且除去文本中的中英文标点符号 2 bvffer = bvffer.lower().replace(ch, " ")
改为:(即将bvffer.lower()放在for循环外,我个人理解:设改文本有N个单词,前者的复杂度为O(N*N),后者复杂度为O(2N))
1 bvffer = bvffer.lower() # 将文本内容都改为小写 2 for ch in '“‘!;,.?”': # 将文本内容都改为小写且除去文本中的中英文标点符号 3 bvffer = bvffer.replace(ch, " ")
修改前后的对比,发现后者比前者快0.2秒左右。(图一是修改前,图二是修改后)
图 一
图 二