代码改变世界

软工作业 5:词频统计——增强功能

2018-12-02 20:43  潘博  阅读(163)  评论(1编辑  收藏  举报

一、基本信息

      1.1 编译环境、项目名称、作者  

1 #编译环境:python3.6
2 #项目名称:软工作业5-词频统计—增强功能
3 #作者:1613072055 潘博
4 #     1613072056 侯磊

   1.2项目地址

  • 本次作业地址:  https://www.cnblogs.com/panboo/
  • 项目git地址:  https://gitee.com/ntucs/PairProg/tree/SE055_056

二、项目分析

  •  程序运行模块(方法、函数)介绍    

    Task 1. 接口封装 —— 将基本功能封装成(类或独立模块)  

    将基本功能:统计文本总词数,统计文本最多的十个单词及其词频这两个方法封装在类Core中,使用面向对象的思想将两个基本功能解耦合,

使之成为通用的方法。

 1 # encoding = utf-8
 2 import re
 3 
 4 class Core:
 5     def process_file(dst):  # 读文件到缓冲区
 6         try:  # 打开文件
 7             file1 = open(dst, "r")
 8         except IOError as s:
 9             print(s)
10             return None
11         try:  # 读文件到缓冲区
12             bvffer = file1.read()
13         except:
14             print("Read File Error!")
15             return None
16         file1.close()
17         return bvffer
18 
19     def word_count(self, bvffer):
20         #bvffer = self.process_file(dst) # 调用方法读数据到缓存区
21         try:
22             count = 0
23             # 统计行数
24             for i in bvffer:  # 统计文件内容中换行符的数目
25                 if i == '\n':
26                     count += 1
27             return count
28         except:
29             print("Read File Error!")
30 
31     def word_freq_t10(self, bvffer):
32         #bvffer = self.process_file(dst)  # 调用方法读数据到缓存区
33         stop = open("stopwords.txt", 'r', encoding='UTF-8')  # 停词表的读取
34         stop_file = stop.read()
35         stop_words = stop_file.replace('\n', " ").lower().split()
36         for i in bvffer: # 去除特殊字符
37             if i in '!"#$%&()*+-,-./:;<=>?@“”[\\]^_{|}~':
38                 bvffer = bvffer.replace(i, " ")  # 替换特殊字符
39         words = bvffer.lower().split()
40         if words:
41             Newwords = []
42             words_select = '[a-z]{4}(\w)*'  # 用正则表达式筛选合格单词
43             for i in range(len(words)):
44                 word = re.match(words_select, words[i])
45                 if word:
46                     Newwords.append(word.group())
47         # 统计单词的词频
48         word_freq = {} # 定义字典而非数组
49         for word in Newwords:
50             word_freq[word] = word_freq.get(word, 0) + 1
51         sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True) # 对合格单词词频排序
52         return sorted_word_freq[:10] # 返回排序数组的前十个元素

    

    编写一个test5.py,通过import WordCount5模块,可以在cmd命令行中测试上述的封装类,也可以直接在Pycharm开发环境中测试。

 1 from SE_fifthwork_task1 import WordCount5
 2 import argparse
 3 if __name__ == '__main__':
 4     parser = argparse.ArgumentParser(description="your script description")  # description参数可以用于插入描述脚本用途的信息,可以为空
 5     parser.add_argument('--f', '-f', type=str, default='Gone_with_the_wind.txt', help="读取文件路径")
 6     args = parser.parse_args()  # 将变量以标签-值的字典形式存入args字典
 7     dst = args.f
 8     print(dst)
 9     core = WordCount5.Core()
10     bvffer = WordCount5.Core.process_file(dst)
11 
12     # 任务一 第一个要求测试
13     count = WordCount5.Core.word_count(core, bvffer)
14     print(count)
15 
16     # 任务一: 第二个要求测试
17     # sorted_word_freq = WordCount5.Core.word_freq_t10(core, bvffer)
18     # for item in sorted_word_freq:  # 输出 Top 10 的单词
19     #     print("<%s>:%d " % (item[0], item[1]))

    对任务1的两个基本方法测试所得结果截图如下:

       

  Task 2. 增加新功能

  • 词组统计:能统计文件夹中指定长度的词组的词频
  • 自定义输出:能输出用户指定的前n多的单词与其数量

    封装类Core的代码:

 1 # encoding = utf-8
 2 import re
 3 
 4 
 5 class Core:
 6     def __init__(self, dst, m, n, o):  # dst:文件路径;m:词组长度;n:输出的单词数量
 7         self.dst = dst
 8         self.m = m
 9         self.n = n
10         self.o = o
11 
12     def process_file(self):  # 读取文件
13         try:  # 打开文件
14             file1 = open(self.dst, "r", encoding='GBK')
15         except IOError as s:
16             print(s)
17             return None
18         try:  # 读文件到缓冲区
19             bvffer = file1.read()
20         except:
21             print("Read File Error!")
22             return None
23         file1.close()
24         return bvffer
25 
26     def process_buffer(self, bvffer):
27         if bvffer:
28             chara_num = 0
29             blank = ''
30             for chara in bvffer:  # 统计字母的数目
31                 if chara.isalpha():
32                     chara_num += 1
33             count = 0
34             for i in bvffer:  # 统计文件内容中换行符的数目
35                 if i == '\n':
36                     count += 1
37             if i[-1] != '\n':  # 当文件最后一个字符不为换行符时,行数+1
38                 count += 1
39             for ch in ':,.-_':
40                 bvffer = bvffer.lower().replace(ch, " ")
41             fwords = bvffer.strip().split()
42 
43             for i in range(self.m):
44                 blank += '[a-z]+'
45                 if i < self.m - 1:
46                     blank += '\s'
47             last = re.findall(blank, bvffer)  # 正则查找词组
48             word_freq = {}
49             for word in last:  # 将正则匹配的结果进行统计
50                 word_freq[word] = word_freq.get(word, 0) + 1
51             return word_freq, chara_num, len(fwords), count
52 
53     def output_result(self, word_freq):
54         if word_freq:
55             sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True)
56             for item in sorted_word_freq[:self.n]:  # 输出 Top n 的单词
57                 print("<%s>:%d " % (item[0], item[1]))
58         return sorted_word_freq[:self.n]
59 
60     def print_result(self):
61         print('读入的文件路径为:' + str(self.dst))
62         print('统计词组长度为:' + str(self.m))
63         print('输出的单词数量为:' + str(self.n))
64         print('文件的存储路径为:' + str(self.o))
65         buffer = Core.process_file(self)
66         word_freq, characters, count_words, count = Core.process_buffer(self, buffer)
67         print("characters:%d " % characters)
68         print("lines:%d " % count)
69         print("words:%d " % count_words)
70         items = Core.output_result(self, word_freq)
71         f = open(self.o, 'w+')
72         print("characters:%d " % characters, file=f)
73         print("lines:%d " % count, file=f)
74         print("words:%d " % count_words, file=f)
75         for item in items:  # 格式化
76             item = '<' + str(item[0]) + '>:' + str(item[1]) + '\n'
77             f.write(item)
78         f.close()
79 
80 
81 if __name__ == '__main__':
82     test = Core('Gone_with_the_wind.txt', 3, 5, 'main.txt')
83     test.print_result()

    

    import argparse模块进行命令行传参测试代码:

 1 # encoding = utf-8
 2 import WordCount5
 3 import argparse
 4 
 5 
 6 if __name__ == '__main__':
 7     parser = argparse.ArgumentParser(description="your script description")  # description参数可以用于插入描述脚本用途的信息,可以为空
 8     parser.add_argument('--i', '-i', type=str, default='Gone_with_the_wind.txt', help="读取的文件路径")
 9     parser.add_argument('--m', '-m', type=int, default=2, help="词组包含单词数量")
10     parser.add_argument('--n', '-n', type=int, default=5, help="输出的词组数量")
11     parser.add_argument('--o', '-o', type=str, default='result.txt', help="存储文件路径")
12     args = parser.parse_args()  # 将变量以标签-值的字典形式存入args字典
13     dst = args.i
14     m = args.m
15     n = args.n
16     o = args.o
17     test5 = WordCount5.Core(dst, m, n, o)
18     test5.print_result()

    

    运行成果图:

    ①使用 -i 传递参数“读取的文件路径

 

     ①使用 -m 传递参数“词组包含单词数量

 

    使用 -n  传递参数  “输出的词组数量

    使用 -0 传递参数  “存储文件路径

     ④-0 -i -m -n 一起使用

 

 

三、性能分析

  本次实验在作业4基础上进行,在时间、空间复杂度方面差不多,所以运行很流畅。

  1.根据执行时间分析

 

  2、性能图表:

 

四、PSP 表格

 

 

五、事后分析与总结

  1 在封装Core模块时——讨论过程

  在解决封装方式时,我们两位同学在解决方法方面出现了分歧。

  55号潘博考虑在设计和实现一个客观系统时,在满足需求的条件下,把系统设计成一些不可变的(相对固定)部分组成的最小集合(最好的设计)。

这些不可变的部分就是所谓的对象。也就是使用面向对象的思想将原来我们写的作业4的项目进行分解成可复用的类方法,从而达到易维护和易扩展的

特点。

  56号侯磊同学认为使用面向过程,将所有业务逻辑写在一起,可以减少代码量并且容易实现,相对来说性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。

  最后,我们综合考虑是作业要求和开发模式优缺点,决定使用潘博同学的方法。

  2 互相评价

  潘博评价侯磊:侯磊同学虽然在编程方面基础不是很好,但是在合作的过程中积极为项目做贡献,在查阅资料与学习

方面不遗余力。美中不足的是对编写程序背后的逻辑方面,不够严谨,希望以后能够多加思考。

  侯磊评价潘博:潘博同学不管在编程能力还是在技术储备方面都非常优秀,能够灵活运用已经学习的各门专业知识,

并且在代码编写与调试方面也非常熟练。在完成任务的同时,积极帮助我解答疑问,受益匪浅,期待下一次的合作。

  3 评价整个过程

  我们觉得,从本次作业完成的过程中,理解了软件工程不仅仅是一门关于程序编写与设计的学科,他还是一门包含“人”

的学科,甚至团队合作是软件开发中的至关重要的一环。

  4.结对编程照片

 

 

  5.其他

    经过这两次的合作编程,我们双方的编程能力都有提高。在合作的过程中,我们互相学习、帮助,一起解决问题,这两次的合作对我们非常有意义。