软工作业3:词频统计

一、编译环境

 (1)测试工具:Pycharm Edu 2017

   (2) python版本:3.6.4

 

二、程序分析

(1)读文件到缓冲区

 1 def process_file(path):  # 读文件到缓冲区
 2     try:   # 打开文件
 3         f = open(path, 'r')   # path为文件路径
 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

(2)处理缓冲区,统计每个单词频率

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)输出频率前十的单词

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)主函数调用前面已封装的函数

if __name__ == "__main__":
    path = "Gone_with_the_wind.txt"  # 《飘》文件的路径
    bvffer = process_file(path)
    word_freq = process_buffer(bvffer)
    output_result(word_freq)

 

三、代码风格说明

(1)python与其他编程语言很大不同是在于没有分号以及花括号,所以python对于空格要求很高,不能使用tab缩进,否则会报IdentationError;

(2)使用try-except的时候,PyCharm在except单词上提示:too broad exception clause,此时需要在try上面加#noinspection PyBroardException;

  (3)UTF-8和GBK是两种不同编码,有时乱码的原因是因为编码格式没调;

(4)python2和python3在输出上写法不同,python3的print是一个函数,要加括号;

 

四、程序运行结果截图

1.Pycharm中运行Gone_with_the_wind.txt结果

 

2.运行A_Tale_of_Two_Cities结果

 

五、性能分析结果及改进

(1)性能分析代码

def main():  # main函数封装词频运行
    path = "Gone_with_the_wind.txt"
    bvffer = process_file(path)
    word_freq = process_buffer(bvffer)
    output_result(word_freq)


if __name__ == "__main__":
    import cProfile
    import pstats
    cProfile.run("main()", filename="word_freq.out")
    # 创建Stats对象
    p = pstats.Stats('word_freq.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):每个函数调用的具体信息;

(2)执行时间最长的代码

for ch in '“‘!;:,.?”':
            bvffer = bvffer.lower().replace(ch, " ")

 

 

(3)执行次数最多的代码

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

(4)使用可视化工具进行分析

(5)代码改进

将bvffer.lower()放到for循环外

修改后代码:

bvffer = bvffer.lower()
        # 将文本内容都改为小写且去除文本中的中英文标点符号
        for ch in '“‘!;:,.?”':
            bvffer = bvffer.replace(ch, " ")
        # strip()删除空白符(包括'/n', '/r','/t');split()以空格分割字符串

修改前性能分析图:

修改后性能分析图:

可以看出比原来快了0.247s。

 

posted @ 2018-10-09 23:08  tsctsc  阅读(311)  评论(1编辑  收藏  举报