2020软件工程第一次个人编程作业
2020软件工程第一次个人编程作业
这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/SE2020 |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/SE2020/homework/11167 |
这个作业的目标 | 1.学会写代码 2.学会搜索 3.提高个人编程能力 |
学号 | 031802638 |
psp表格
PSP2.1 | Personal Software Process Stages | 预估耗时 | 实际耗时) |
---|---|---|---|
Planning | 计划 | 3h | 1h |
Estimate | 估计这个任务需要多少时间 | 3day | 5day |
Development | 开发 | 5h | 2day |
Analysis | 需求分析 (包括学习新技术) | 1day | 1day |
Design Spec | 生成设计文档 | 1h | 1h |
Design Review | 设计复审 | 1h | 1h |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 1h | 1h |
Design | 具体设计 | 1h | 1h |
Coding | 具体编码 | 6h | 6h |
Code Review | 代码复审 | 1h | 1h |
Test | 测试(自我测试,修改代码,提交修改) | 3h | 3h |
Reporting | 报告 | 3h | 3h |
Test Report | 测试报告 | 1h | 1h |
Size Measurement | 计算工作量 | 1h | 1h |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 2h | 2h |
解题思路
思路图
拿到题目之后,肯定是先看题目啊,原来是解析 json,初步想法是解析 json,存储数据。
那怎么实现呢????
实现过程
参数引入
python中有两种比较方便的方式引入参数
- 1.sys
import sys
print ('参数个数为:', len(sys.argv), '个参数。')
print ('参数列表:', str(sys.argv))
运行实例
- 2.argparse
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-u','--user')
print(parser.parse_args().user)
运行实例
扫描文件夹及 json 文件导入
json_list = []
for root, dic, files in os.walk(dict_address):
for f in files:
if f[-5:] == '.json': # 文件名后5个字符为 .json 则为 json 文件
json_path = f
x = open(dict_address+'\\'+json_path,
'r', encoding='utf-8').read()
str_list = [_x for _x in x.split('\n') if len(_x) > 0]
for i, _str in enumerate(str_list):
try:
json_list.append(json.loads(_str)) # 反序列化 将 string 类型解析为 dict
except:
pass
该段代码对文件夹进行扫描,找到 json 文件,打开文件, json.loads() 针对内存对象将 string 转为 dict ,如果有写过 java 和 c 就会发现python的语法特别的简洁与方便
文件内容解析
核心代码
def __parseDict(self, d: dict, prefix: str):
_d = {}
for k in d.keys():
if str(type(d[k]))[-6:-2] == 'dict':
_d.update(self.__parseDict(d[k], k))
else:
_k = f'{prefix}__{k}' if prefix != '' else k
_d[_k] = d[k]
return _d
def __listOfNestedDict2ListOfDict(self, a: list):
records = []
for d in a:
_d = self.__parseDict(d, '')
# print(_d.get('type'))
if _d.get('type',0) in ['PushEvent','IssueCommentEvent','IssuesEvent','PullRequestEvent']:
records.append(_d)
return records
解析 dict ,将嵌套的 dict 解析出来 , 生成类似以下的数据:
{"id":"24903941032","actor__login":"petroav","repo__name":"petroav"}
这部分是初始化耗时最大的部分
写入 json 文件
records = self.__listOfNestedDict2ListOfDict(json_list)
self.__4Events4PerP = {}
self.__4Events4PerR = {}
self.__4Events4PerPPerR = {}
for i in records:
if not self.__4Events4PerP.get(i['actor__login'], 0):
self.__4Events4PerP.update({i['actor__login']: {}})
self.__4Events4PerPPerR.update({i['actor__login']: {}})
self.__4Events4PerP[i['actor__login']][i['type']
] = self.__4Events4PerP[i['actor__login']].get(i['type'], 0)+1
if not self.__4Events4PerR.get(i['repo__name'], 0):
self.__4Events4PerR.update({i['repo__name']: {}})
self.__4Events4PerR[i['repo__name']][i['type']
] = self.__4Events4PerR[i['repo__name']].get(i['type'], 0)+1
if not self.__4Events4PerPPerR[i['actor__login']].get(i['repo__name'], 0):
self.__4Events4PerPPerR[i['actor__login']].update({i['repo__name']: {}})
self.__4Events4PerPPerR[i['actor__login']][i['repo__name']][i['type']
] = self.__4Events4PerPPerR[i['actor__login']][i['repo__name']].get(i['type'], 0)+1
with open('1.json', 'w', encoding='utf-8') as f:
json.dump(self.__4Events4PerP,f)
with open('2.json', 'w', encoding='utf-8') as f:
json.dump(self.__4Events4PerR,f)
with open('3.json', 'w', encoding='utf-8') as f:
json.dump(self.__4Events4PerPPerR,f)
这部分代码用于从 解析好的 dict 里找到有用的数据 分别写入三个 json 文件
学习历程
学习的过程肯定是艰难的呀,看到助教老师的 python 让人恍然大悟,原来可以这样解析 json ,之前的我可只会无情的调包
- ptyhon 初始化参数
之前会很好奇,一些在命令行中的代码是怎么读取参数的,在了解了 parser 库之后,对参数的引入更加了解了 - json 的解析
如果是之前的我,肯定就掉包解析 json 了,现在看了这串代码,觉得知识又增加了 - 编程的新思维
从面向过程的思维转向了对类的初始化,学到了新的编程思想 - 其他
助教老师的代码写的好好,python代码有很大部分是可以直接使用的,提高效率才是关键
优化方法
1.文件读入优化
2.异步多线程处理
3.json解析优化
4.一些字符串操作的优化
pr截图
- CI
单元测试
单元覆盖率
代码规范
https://github.com/Yamyyy/2020-personal-python/blob/master/codestyle.md
总结
在本次作业中,我学到了很多,从安装 python 到可以独立开发一个 python 小功能,学会了新的编程方法,有了属于自己的代码规范,知道了时间很珍贵,要好好敲代码,有很多知识还不会,要赶紧学