软工作业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秒左右。(图一是修改前,图二是修改后)

       

                                 图 一

                                 图 二

posted @ 2018-09-28 17:38  高昶  阅读(483)  评论(2编辑  收藏  举报