• 软工作业3:词频统计个人编程练习


     一、编译环境说明

      (1)python3.7.1

      (2)pycharm2018

    二、程序分析,对程序中的四个函数做简要说明

    (1)读文件到缓冲区(process_file(dst))

    def process_file(dst):  # 读文件到缓冲区
        try:     # 打开文件
            file = open(dst, 'r')  # dst为文本的目录路径
        except IOError as s:
            print(s)
            return None
        try:     # 读文件到缓冲区
            bvffer = file.read()
        except:
            print("Read File Error!")
            return None
        file.close()
        return bvffer

     

    (2)处理缓冲区,返回存放每个单词频率的字典word_freq(process_buffer(bvffer))

    def process_buffer(bvffer):  # 处理缓冲区,返回存放每个单词频率的字典word_freq
        if bvffer:
            # 下面添加处理缓冲区bvffer代码,统计每个单词的频率,存放在字典word_freq
            word_freq = {}
            # 将文本内容都改为小写且去除文本中的中英文标点符号
            for ch in '“‘!;,.?”':
                 bvffer = bvffer.lower().replace(ch, " ")
            # strip()删除空白符(包括'/n', '/r','/t');split()以空格分割字符串
            words = bvffer.strip().split()
            for word in words:
                word_freq[word] = word_freq.get(word, 0) + 1
            return word_freq

     

    (3)输出出现频率排在前十的单词(output_result(word_freq))

    def output_result(word_freq): # 出现频率排在前十的单词
            if word_freq:
                sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True)
                for item in sorted_word_freq[:10]:  # 输出 Top 10 的单词
                    print("单词:%s 频数:%d " % (item[0], item[1]))

     

    (4)main()函数

    def main():
        dst = "txt/Gone_with_the_wind.txt"  # 《Gone_with_the_wind》的路径,另一组测试更改为《A_Tale_of_Two_Cities》的路径
        bvffer = process_file(dst)
        word_freq = process_buffer(bvffer)
        output_result(word_freq)

     

    (5)主函数进行调用

    if __name__ == "__main__":
        main()

     

    三、代码风格说明

      Python 代码强调即使是一个打算被用作脚本的文件,也应该是可导入的。并且简单的导入不应该导致这个脚本的主功能(main functionality)被执行,这是一种副作用.。主功能应该放在一个main()函数中。

      在Python中,pydoc以及单元测试要求模块必须是可导入的。你的代码应该在执行主程序前总是检查if_name_=='_main_',这样当模块被导入时主程序就不会被执行。

      例如程序中第48行代码:

    def main():
        dst = "txt/Gone_with_the_wind.txt"  # 《Gone_with_the_wind》的路径,另一组测试更改为《A_Tale_of_Two_Cities》的路径
        bvffer = process_file(dst)
        word_freq = process_buffer(bvffer)
        output_result(word_freq)
    
    if __name__ == "__main__":
        main()

      

    四、程序运行命令、运行结果截图

    (1)对文件《A_Tale_of_Two_Cities》进行词频统计

            ①在pycharm2018中运行的结果截图

            

            ②在DOS命令行中运行的命令、结果截图

            

     

    (2)对文件《Gone_with_the_wind》进行词频统计

            ①在pycharm2018中运行的结果截图

            

            ②在DOS命令行中运行的命令、结果截图

            

     

    五、性能分析结果及改进 

    (1)代码

    if __name__ == "__main__":
        import cProfile
        import pstats
    
        cProfile.run("main()", filename="result.out")
        # 创建Stats对象
        p = pstats.Stats('result.out')
        # 输出调用此处排前十的函数
        # sort_stats(): 排序
        # print_stats(): 打印分析结果,指定打印前几行
        p.sort_stats('calls').print_stats(10)
        # 输出按照运行时间排名前十的函数
        # strip_dirs(): 去掉无关的路径信息
        p.strip_dirs().sort_stats("cumulative", "name").print_stats(10)
    
        # 根据上面的运行结果发现函数process_buffer()最耗时间
        # 查看process_buffer()函数中调用了哪些函数
        p.print_callees("process_buffer")

     备注:ncalls:表示函数调用的次数;
               tottime:表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间;
               percall:(第一个percall)等于 tottime/ncalls;
               cumtime:表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间;
               percall:(第二个percall)即函数运行一次的平均时间,等于 cumtime/ncalls;
               filename:lineno(function):每个函数调用的具体信息;

         

            ①指出寻找执行时间最多的部分代码:

              

                 该部分代码为:

    # 将文本内容都改为小写且去除文本中的中英文标点符号
            for ch in '“‘!;,.?”': 
                bvffer = bvffer.lower().replace(ch, " ")

     

            ②指出寻找执行次数最多的部分代码:

            

                 该部分代码为: 

       for word in words:
           word_freq[word] = word_freq.get(word, 0) + 1

     

    (2)使用可视化工具分析

            ①可视化工具:选用graphviz、gprof2dot 

            ②对保存分析结果的result.out文件进行可视化

            

                    

     

    (3)代码改进尝试

           ①代码修改:对执行时间最久的部分代码做出修改

               原代码:

     # 将文本内容都改为小写且去除文本中的中英文标点符号
            for ch in '“‘!;,.?”':
                bvffer = bvffer.lower().replace(ch, " ")

               修改后:

            #代码性能改进
            # 将文本内容都改为小写
            bvffer = bvffer.lower()
            # 去除文本中的中英文标点符号
            for ch in '“‘!;,.?”':
                bvffer = bvffer.replace(ch, " ")

           ②修改前该部分代码耗时情况:

               

               修改后该部分代码耗时情况:

               

               经对比发现运行时间由0.253降低为0.034。

  • 相关阅读:
    oracle锁---原理篇
    SML + NL + HJ
    Oracle中varchar,varchar2,nvarchar,nvarchar2的区别
    oracle 一致读原理
    commit 流程
    IMPDP NETWORK_LINK参数
    WINDOWS访问虚拟机RedHat搭配的Apache2服务器
    初识malloc函数
    好吧,又失眠
    休息一天
  • 原文地址:https://www.cnblogs.com/fighting2015/p/9754994.html
Copyright © 2020-2023  润新知