软工作业 5:结对项目之词频统计——增强功能

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


一、基本信息

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

1 #编译环境:python3,Geany
2 #项目名称:结对项目词之词频统计—增强功能
3 #作者:1613072037 张铭锐
4 #         1613072036 谭琪

   1.2项目地址

二、项目分析

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

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

    将基本功能:统计文本总词数,统计文本最多的十个单词及其词频这两个方法封装在类wordclass中

 1 #coding=gbk
 2 import re
 3 
 4 class wordclass:
 5 
 6     def process_file(dst):  # 读取文件
 7         countline = len(open(dst, 'r').readlines())  # 文本的行数countline
 8         with open(dst) as f:
 9             bvffer = f.read()
10         f.close()
11         return bvffer
12 
13     def process_buffer(bvffer):
14            if bvffer:
15                for ch in '“‘!;:,.?”':
16                    bvffer = bvffer.lower().replace(ch, " ")
17                wordmatch = "^[a-z]{4}(\w)*"  #正则表达式至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写
18          # 将文本内容都改为小写且去除文本中的中英文标点符号
19                words = []
20                for i in range(len(bvffer)):
21                    word = re.match(wordmatch, bvffer[i])  # 匹配list中的元素
22                    if word:  # 匹配成功,加入words
23                        words.append(word.group())
24                # strip()删除空白符(包括'/n', '/r','/t');split()以空格分割字符串
25                words = bvffer.strip().split()
26                word_freq = {}
27                for word in words:  # 对words进行统计
28                    word_freq[word] = word_freq.get(word, 0) + 1
29            return word_freq, len(words)
30 
31     def output_result(word_freq):
32            if word_freq:
33                sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True)
34                for item in sorted_word_freq[:10]:  # 输出 Top 10 的单词
35                    print("单词:%s 频数:%d " % (item[0], item[1]))
36            return sorted_word_freq[:10]
37 
38     def result(dst):
39         buffer = wordclass.process_file(dst)
40         word_freq, countwords = wordclass.process_buffer(buffer)
41         print('文本总单词数:' + str(countwords))
42         print('文本中最多的10个单词及其词频')
43         wordclass.output_result(word_freq)

    编写一个test.py,通过import argparse模块,可以在cmd命令行中测试上述的封装类

1 #coding=gbk
2 import WordCount
3 import argparse
4 if __name__ == '__main__':
5     parser = argparse.ArgumentParser(description="your script description")  # description参数可以用于插入描述脚本用途的信息,可以为空
6     parser.add_argument('--file', '-file', type=str, default='D:/桌面/python_work/SE037/Gone_with_the_wind.txt', help="读取文件路径")#default属性是默认值,当参数输入错误时使用默认参数 type后表示参数的类型 
7     args = parser.parse_args()  # 将变量以标签-值的字典形式存入args字典
8     path = args.file #通过键值对形式取值
9     WordCount.wordclass.result(path) #此处为类的调用

    

    下图为统计所用的文本Gone_with_the_wind_txt 

 

     下图为在IDE环境下运行截图

 

     下图为在命令行传参截图

扫描二维码关注公众号,回复: 4303172 查看本文章

  Task 2. 增加新功能

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

    封装类wordclass的代码:

 1 #coding=gbk
 2 import re
 3 class wordclass:
 4     def __init__(self,path,m,n,o):   #类wordclass的构造方法  path为文件路径  m为词组长度  n为输出单词数量  o为生成的result文件存储路径
 5         self.path=path
 6         self.m=m
 7         self.n=n
 8         self.o=o
 9 
10     def process_file(self):
11         countline = len(open(self.path, 'r').readlines())  # countline为文本行数
12         with open(self.path) as f:
13             bvffer = f.read()
14         f.close()
15         return bvffer, countline
16 
17 
18     def process_buffer(self,bvffer):  # 处理缓冲区,返回存放每个单词频率的字典word_freq
19         if bvffer:
20             word_freq = {}
21             words = []
22             for ch in '“‘!;:,.?”':  
23                 bvffer = bvffer.lower().replace(ch, " ")
24             words = bvffer.strip().split()
25             match='[a-z]+'
26             for i in range((self.m)-1):
27                 match+='\s[a-z]+'   #m长度词组的正则表达式
28             result = re.findall(match, bvffer)  # 正则查找词组
29             for word in result:
30                 word_freq[word]=word_freq.get(word,0)+1
31             return word_freq,len(words)
32 
33 
34 
35     def output_result(self,word_freq):
36         if word_freq:
37             sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True)
38             for item in sorted_word_freq[:self.n]:  # 输出 Top n 的单词
39                 print("单词:%s 频数:%d " % (item[0], item[1]))
40         return sorted_word_freq[:self.n]
41 
42     def result(self):
43         print('需查询的文本路径:'+str(self.path))
44         print('需查询的词组长度:'+str(self.m))
45         print('需查询的词频Top:'+str(self.n))
46         buffer,countline=wordclass.process_file(self)
47         word_freq,lenwords=wordclass.process_buffer(self,buffer)
48         clines= 'lines:' + str(countline)
49         cwords = 'words:' + str(lenwords)
50         print(clines)
51         print(cwords)
52         items =wordclass.output_result(self,word_freq)
53         with open(self.o, 'w') as w:
54             w.write(clines+'\n')
55             w.write(cwords+'\n')
56             for item in items:  # 格式化
57                 item = '<' + str(item[0]) + '>:' + str(item[1]) + '\n'
58                 w.write(item)
59         print('将该文件写入路径为:'+self.o)
60         w.close()
61 
62 
63 
64 
65 
66 #if __name__ == '__main__':
67 #     obj = wordclass('D:/桌面/python_work/Gone_with_the_wind.txt', 2, 3, 'D:/桌面/python_work/SE037/result.txt')
68 #     obj.result()
69 
70 
71 
72 
73  

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

 1 #coding=gbk
 2 import wordclass
 3 import argparse
 4 import cProfile
 5 import pstats
 6 
 7 def main():
 8     parser = argparse.ArgumentParser(description="your script description")  #   创建一个解析对象 description参数可以用于插入描述脚本用途的信息,可以为空
 9     parser.add_argument('--i', '-i', type=str,required=True,help="读取文件路径")#添加--i标签,标签别名可以为-i,required=Truerequired表示---参数是必需的,并且类型为str,输入别的类型会报错。
10     parser.add_argument('--m', '-m', type=int,required=True,help="输出的单词数量")
11     parser.add_argument('--n', '-n', type=int,required=True,help="输出的单词数量")
12     parser.add_argument('--o', '-o', type=str,required=True,help="读取文件路径")
13     args = parser.parse_args()  # 进行解析 将变量以标签-值的字典形式存入args字典
14     path = args.i
15     m = args.m
16     n = args.n
17     o = args.o
18     obj = WordCount.wordclass(path, m, n, o)
19     obj.result()
20 if __name__ == '__main__':
21     cProfile.run("main()", "pstats_result")
22     # 把分析结果保存到文件中,不过内容可读性差...需要调用pstats模块分析结果
23     p = pstats.Stats("pstats_result")  # 创建Stats对象
24     p.strip_dirs().sort_stats("call").print_stats()  # 按照调用的次数排序
25     p.strip_dirs().sort_stats("cumulative").print_stats()  # 按执行时间次数排序

    运行成果图:

 

三、性能分析

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

  1.根据调用次数分析

 

  2.根据执行时间分析

  性能图表:

四、PSP 表格

五、事后分析与总结

  1.简述结对编程时,针对某个问题的讨论决策过程

    我们在网上查找了python命令行传参的方式,了解到传递参数有三种方法:1、参数通过sys.argv传递,它的类型是一个list类型,其中的元素为字符串。2、通过getopt模块解析Python传入的参数,它能解析带'-'和'--'格式的参数。它的函数原型为:getopt.getopt(args, options[, long_options])。3、使用argparse模块解析命令行参数。通过我和谭琪的讨论,我们选择了argparse模块来传参,因为argparse是一个可以自动生成帮助信息和错误信息的模块,有利于命令行传参的调试分析。

  2.评价对方:请评价一下你的合作伙伴,又哪些具体的优点和需要改进的地方。 这个部分两人都要提供自己的看法。

    谭琪评价张铭锐:张铭锐同学在编程方面能力很强,在python语言方面很熟练,也很有自己的编程想法。需要改进的地方:在编码过程中需要能够灵活变通。

    张铭锐评价谭琪:谭同学做项目态度很认真,学习能力也很强,我们一开始对python命令行传参不是很了解,他通过学习csdn中的相关帖子教程后掌握了这些方法。需要改进的地方:虽然python基础还不错,但还需要学习python深层次的知识。

  3.评价整个过程:关于结对过程的建议

    结对编程需要双方不断提出自己的想法并加以结合,耐心理解对方的思路。每人负责相应的模块,但也要融会对方的进程,相互补充和学习。在解决问题的过程中,我们相互启发和纠正,对于有争议的问题也是通过实践来印证。通过此次的结对编程,我们体会到合作的重要性以及不理解对方时的艰难,使我们对合作开发有了一定的理解和基础。

  4.结对编程照片

  5.其他

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

猜你喜欢

转载自www.cnblogs.com/psglgdzmr/p/10042706.html
今日推荐