(1)Fork仓库的Github项目地址。
GitHub地址 | 结队GitHub |
---|---|
本人学号 | 201831061216 |
伙伴学号 | 201831061217 |
伙伴博客地址 | 地址 |
(2)psp表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 40 |
Estimate | 估计这个任务需要多少时间 | 半周 | 3天 |
Development | 开发 | 500 | 700 |
Analysis | 需求分析 (包括学习新技术) | 200 | 400 |
Design Spec | 生成设计文档 | 30 | 20 |
Design Review | 设计复审 (和同事审核设计文档) | 120 | 150 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 40 |
Design | 具体设计 | 60 | 40 |
Coding | 具体编码 | 600 | 900 |
Code Review | 代码复审 | 120 | 120 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 180 | 250 |
Test Report | 测试报告 | 60 | 40 |
Size Measurement | 计算工作量 | 20 | 5 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 60 | 40 |
合计 | 2160 | 3天 |
(3) 计算模块接口的设计与实现过程。
代码分析
整体代码使用5个函数实现的,其中四功能函数,一个工具函数通过-i -o -u -e 命令来调用已经封装好的四个功能函数。
-i __.txt实现对文本里的字符的数量的统计
思路使用文件里的方法f.read()将读取到的信息存放到字符串中然后求取字符串的长度。
def My_chars_count(file_name):
#用来统计文本文件里面的字符数量
with open(file_name,'r') as f:
chars=f.read()
f.close()
return 'chars:'+str(len(chars))
-o__.txt实现对文本文件符合条件的单词数量进行统计
思路:使用了正则表达式,之前就听说过但是一直没有去学习,这次是一个很好的机会去了解正则表达式。用readlines()的方法把文本文本以行的方式读取出来,然后在对每一行进行字符串匹配,符合以4个字母开头的单词就会以列表的形式输出再将其存入定义过的word单词列表,求出word的长度就是单词的数量
def My_words_count(file_name):
#用来统计文本文件里面的单词数量规定4个字母以上的单词
words=[]
word=0
with open(file_name,'r') as f:
lines=f.readlines()
for N in range(0,len(lines)):
#正则表达式把符合条件的单词筛选出来
words.extend(re.findall(r'[(a-z|A-Z)(a-z|A-Z)(a-z|A-Z)(a-z|A-Z)]{4,}',lines[N]))
word+=len(words)
f.close()
return "words:"+str(word)
-u__.txt实现对文本文件有效行数的统计
思路:有效行数即非空白行,空白行就是'\n'那么利用if语句就可以控制计数器的自增实现对于非空白行的计数。
def My_lines_count(file_name):
#用来统计文本文件里面的行数
line_num=0
with open(file_name,'r') as f:
lines=f.readlines()
for each_line in lines:
if each_line!='\n':
line_num+=1
f.close()
return "lines:"+str(line_num)
-e__.txt实现对文本文件单词出现频率的统计
思路:这个函数的前一部分和-u基本一致,利用正则表达式选出单词存入一个有重复的列表,接着利用python中的dict字典类型的特征,dict{key:value}key和value是映射关系不会出现重复的key,那么就把不重复的单词给key,单词的频率用value的值来记录。有重复单词的列表和字典和无重复单词的列表好像三个杯子,有重复单词->字典->无重复单词的列表就像一个杯子的水依次倒给下一个水杯倒三次水水变少了。
在python的list列表中有一个方法list.count()(i)用来求得第i个列表元素在列表中的个数,用这个方法来解决这个问题在合适不过了。那么我们遍历无重复的单词列表让这个单词在有重复的单词列表中来求得重复的次数就可以了。
def word_count(file_name):
#记录文本中单词出现的频率,并且按照出现频率打印出来
#words列表存放有重复的单词
words=[]
with open(file_name,'r') as f:
lines=f.readlines()
for N in range(0,len(lines)):
words.extend(re.findall(r'[(a-z|A-Z)(a-z|A-Z)(a-z|A-Z)(a-z|A-Z)]{4,}',lines[N]))
#利用了python字典的特性dict{key:value},字典里面映射关系不会出现键key的重复
#创建一个字典存放单词和其频率
wokey={}
#用有重复单词的列表来给字典赋值,而在字典中就不会用重复了但是key对应的value的值没有变的
wokey=wokey.fromkeys(words)
#新定义一个单词列表来存放无重复的单词
wordlist=list(wokey.keys())
for i in wordlist:
#得到无重复的词频
wokey[i]=words.count(i)
wokey_1={}
wokey_1=sorted(wokey.items(),key=lambda p:p[1],reverse=1)
i=0
for x,y in wokey_1:
if i<10:
print('%s’s frequence: %d'%(x,y))
i+=1
continue
else:
break
f.close()
-d 增加功能求指定长度的词组的次数
在第三步中,我们希望各位在第一步的基础上,添加一些新的功能:
a) 词组统计:能统计文件夹中指定长度的词组的词频
思路:因为可以使用正则表达式这个问题变的十分简单了,
r'[(a-z|A-Z)(a-z|A-Z)(a-z|A-Z)(a-z|A-Z)]{3},意思是在筛选前3个字符都是符合a-Z的单词,然后我们对于符合条件的单词进行计数。
def My_dgtwords_count(file_name):
#用来统计文本文件里面的指定单词长度词组词的数量,这里是3个长度的词组
words=[]
word=0
with open(file_name,'r') as f:
lines=f.readlines()
for N in range(0,len(lines)):
words.extend(re.findall(r'[(a-z|A-Z)]{3}',lines[N]))
word+=len(words)
f.close()
return "designatewords:"+str(word)
调用以上功能函数的工具函数
注意实现多个功能时必须按照-i-o-u-e-d的顺序!
实现使用输入的 -i-u-d-o-e 和文件名 得到期望值的功能,这里写函数的时候非常蠢。。。我们没有特别好的方法就是手打各种输入方式然后调用对应函数。缺陷就是不能实现调换输入顺序和同时读取两个文档。
def My_cmd():
command,file_name=input("Please input command").split()
if command=='-i':
#记录字符的数量
print(My_chars_count(file_name))
if command=='-d':
#记录字符的数量
print(My_dgtwords_count(file_name))
if command=='-o':
#记录符合条件单词的数量
print(My_words_count(file_name))
if command=='-u':
#记录有效行数
print(My_lines_count(file_name))
if command=='-e':
#记录词频
print(word_count(file_name))
if command=='-i-o':
#记录字符的数量,记录符合条件单词的数量
print(My_chars_count(file_name))
print(My_words_count(file_name))
if command=='-i-u':
#记录字符的数量,记录有效行数
print(My_chars_count(file_name))
print(My_lines_count(file_name))
if command=='-i-e':
#记录字符的数量,#记录词频
print(My_chars_count(file_name))
print(word_count(file_name))
if command=='-i-o-u':
#记录字符的数量,记录符合条件单词的数量,记录有效行数
print(My_chars_count(file_name))
print(My_words_count(file_name))
print(My_lines_count(file_name))
if command=='-i-o-u-e':
#记录字符的数量记录符合条件单词的数量,记录有效行数,记录词频
print(My_chars_count(file_name))
print(My_words_count(file_name))
print(My_lines_count(file_name))
print(word_count(file_name))
if command=='-i-o-e':
#记录字符的数量记录符合条件单词的数量,记录词频
print(My_chars_count(file_name))
print(My_words_count(file_name))
print(word_count(file_name))
if command=='-o-u':
#记录符合条件单词的数量,有效行数
print(My_words_count(file_name))
print(My_lines_count(file_name))
if command=='-o-e':
#记录符合条件单词的数量和词频
print(My_chars_count(file_name))
if command=='-u-e':
#记录有效行数和词频
print(My_lines_count(file_name))
print(word_count(file_name))
My_cmd()
(4)代码复审过程。
代码复审检查表:
1、概要部分
(1)代码符合需求和规格说明么?
符合。
(2)代码设计是否考虑周全?
是
(3)代码可读性如何?
简单易懂。
(4)有冗余的或重复的代码吗?
开始有冗余但后面在两人协商后由一人改编后没有冗余了。
(5)代码的每一行都执行并检查过了吗?
执行并逐行检查过。
2、设计规范部分
(1)设计是否遵从已知的设计模式或项目中常用的模式?
遵守。
(2)有没有无用的代码可以清除?
没有。
3、代码规范部分
基本符合代码标准和风格,代码可读性高。
4、具体代码部分
数据结构中有没有用不到的元素?
没有
5、效能
代码的效能如何?
效能很高。
6、可读性
可读性比较高,注释很详细。
7、可测试性
进行了单元测试
8、代码复审感想
经过这次的代码复审,我认识到了代码复审可以找出代码的错误,以及发现逻辑和算法的出错,甚至还可能发现潜在的错误,这些能让我们互相在代码复审中互有补益,能够更加开拓我们对编程的理解和认识。 |
(5)计算模块接口部分的性能改进。
性能分析
通过性能分析主要的时间用在了input上面,挺尴尬的。 我们两个进行讨论希望能可以改变一些,但是通过了调整函数并未实现。这或许是由于我们现在所学知识还有限,同时也提醒我们后面还需要增加我们代码量和一些实践经验。 |
(6)计算模块部分单元测试展示。
使用python测试模块uinttest进行测试,代码比较测试结果与预计一样。 |
(7)计算模块部分异常处理说明。
在测试过程中我发现当文本文件里面出现了汉字和一些中文符号后会报错 |
解决方法:
读取方式改成二进制读取方式就可以了。 |
新的错误
改回原来的读取方式后,又出现原来的方式,我们经过一番努力以后并没有解决这个问题,之后再网上复制粘贴来的文本都会有这样的问题所以这也是我们在代码测试复审中发现的缺陷。 |
(8) 描述结对的过程。
代码模块上,由于第一次作业时就划分好了模块,以及对于多个函数的规划和安排都比较清晰,所以在添加新功能时,没有在大的代码模块上出现问题。结对时,我们遇到的困难主要还是在复杂字符串进行操作的算法上。在结对项目的开展初期,我们是在宿舍进行讨论的;我们在宿舍进行需求分析,然后搜索相对应的资料,各自也在进行进度的标记,控制项目的进程。在聊完了各自已经做完的工作之后,我俩一起探讨了当时未解决的问题,我们主要聊了下复杂字符串进行操作,开始这个问题对我们确实很棘手,搞得我们也烦躁,但在后期的讨论中我们烦躁的心情得到缓解,然后我们将我们所遇的问题进行了整理,紧接着我们通过上网查找这个问题的解决方法,功夫不负有心人我们找到了正则表达式来解决这个问题,正则表达式的大致匹配过程是:依次拿出表达式和文本中的字符比较,如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。我们使用正则表达式中的findall(findall 的简单用法:返回string中所有与pattern相匹配的全部字串,返回形式为列表)。结对编程真的很棒,在相互的合作中能够给自己带来很多全新的认识。可以对代码结构进一步的优化,产生新的idea等等。 |
(9)附加功能(用户交互界面)
from tkinter import *
# 导入ttk
from tkinter import ttk
# 导入simpledialog
from tkinter import simpledialog
class App:
def __init__(self, master):
self.master = master
self.initWidgets()
def initWidgets(self):
# 创建3个按钮,并为之绑定事件处理函数
ttk.Button(self.master, text='导入单词文本文件',
command=self.open_string # 绑定open_integer方法
).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)
ttk.Button(self.master, text='输入字符串对话框',
command=self.open_string1 # 绑定open_integer方法
).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)
def open_string(self):
# 调用askstring函数生成一个让用户输入字符串的对话框
print(simpledialog.askstring("导入单词文本文件", "输入–i–e–u–d",
initialvalue='-i'))
def open_string1(self):
# 调用askstring函数生成一个让用户输入字符串的对话框
print(simpledialog.askstring("输入字符串对话框", "输入–i–e–u–d",
initialvalue='-m'))
root = Tk()
root.title("wordcount")
App(root)
root.mainloop()
开始看到这题目的时候确实很伤脑筋,题目中的用户交互界面对现在的我们来说还是比较生疏,因为之前没怎么之前没有用Python做过用户交互界面,对于用户交互界面绘制我们两个商量了很久,我们当时查阅了很多资料网上看了不少视频最后终于做出现在的界面,因为时间原因我们只能完成这么多,虽然现在做的还不是很完美但是在后期的学习中我们会越做越好更上一层楼的。 并且我们在这次作业对于GUI设计充满兴趣。 |
(10)总结
实际操作的时候,分工跟预想的并不完全一样,我们首先讨论出了具体的算法,那些算法改进的话程序效率提高的最多。随后算法的主要代码是我们共同完成的。总的来讲,通过这个过程,还是学到了很多,队友就像一面镜子,我们互相学习互相进步,体验到了1+1>2。 |