#219 实验楼楼赛第3期-Python-题解

因对 Python 感兴趣,于是早上吃早饭时看看。题目相对比较简单,最后一题代码写得比较随意。原本打算交上去测试一下,可惜海外党使用环境实在是卡得惨不忍睹,没办法写敲那么多代码上去。

题目:https://www.shiyanlou.com/contests/lou3/challenges

题目1: 存储学习记录

出现的问题:

  • sqlite url schema 错误
  • 外键设置错误
  • 外键重复设置

解决方法:

  • line 10: sqlite:// 改为 sqlite:///
  • line 22: backref='user' 改为 backref='course'
  • 表设计为一对多的外键,故注释掉 line 28 & line 30

题目2: 追踪课程更新

出现的问题:

  • 缺少 object 基类
  • 缺少子类初始化
  • @property 方法访问错误
  • typename 缺少参数
  • 浅拷贝错误

解决方法:

  • line 5: 改为 class Course(object)
  • line 21: 给 typename 传递参数 self
  • line 28: 替换为 super(BootcampCourse, self).__init__(name, True, lab_count)
  • line 37: 改为调用 self.lab_count
  • line 29: 改为调用 copy.deepcopy

题目3: 修复 Internal Server Error

出现的问题:

  • filter_by 用法错误
  • html 模板错误

解决方法:

  • app/main/views.py line 34: filter_by(id=id).first_or_404()
  • app/templates/todolist.html line 4: for('static', filename='js/todolist.js')
  • app/templates/todolist.html line 9:

题目4: NoSQL 的艺术

潜在的问题:

  • 从 bash 中读入的值为字符串
  • mongodb 的 aggregate pipeline 操作
  • sort 结果搜索: mongodb 的 aggregate 操作找了半天实在没找到如何从操作结果的 cursor 拿到排名,只得做如下妥协处理,读者可继续探究
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# TODO: return the rank of user_id
user_id = int(user_id)
results = contests.aggregate([
{
'$group': {
'_id': '$user_id',
'sum_score': {'$sum': '$score'},
'sum_time': {'$sum': '$submit_time'}
}
},
{
'$sort': {
'sum_score': -1,
'sum_time': -1
}
}
])
# CRISES: id_list may cause large memory consumption
id_list = [int(value['_id']) for value in results]
# INPROVEMENTS: could use binary search
try: return id_list.index(user_id)+1
except: return 0

题目5: 增加服务器管理功能

潜在的问题:

  • 异常处理方式: 异常处理的部分原题目似乎并未写指示清楚, 这里用直接抛出 ScriptError 异常做处理
  • csv 文件处理: 虽然其实并不是 csv 格式,但由于带空格的形式可以视为 csv 文件进行处理; 另一方面文件操作似乎并不支持单独一行的处理操作?
  • 重复添加操作判断: 重复添加的判断逻辑应为: 当 hostip 和 user 同时相同时,则不能添加,否则可添加。
  • 命令行参数处理: 最初决定使用 argparse 处理命令行参数,扫文档扫了半天没搞明白怎么添加 subparameter requirement,google 了一阵也很奇怪,最后还是决定直接暴力解包判断了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import sys
import csv

class ScriptError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr('ERROR:'+self.value)

def listinfo():
with open('serverinfo', 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=' ')
for row in reader:
print ' '.join(row)

def addinfo(hostip, user, password):
with open('serverinfo', 'r+') as csvfile:
reader = csv.reader(csvfile, delimiter=' ')
contents = []
new = [hostip, user]
for row in reader:
contents.append([row[0], row[1]])
if new not in contents:
writer = csv.writer(csvfile, delimiter=' ')
writer.writerow([hostip, user, password])
else:
raise ScriptError('user exists')

def deleteinfo(hostip):
f = open('serverinfo', 'r')
lines = f.readlines()
f.close()
f = open('serverinfo', 'w')
for line in lines:
if hostip not in line:
f.write(line)
f.close()

def main():
if len(sys.argv) < 2:
print """
Usage:
======
python server.py [add|delete|list]

add: add info, required parameter below
-h hostip
-u user
-p password
delete: delete info, required parameter below
-h hostip
list:list all info
"""
elif sys.argv[1] == 'add':
if (sys.argv[2] == '-h' or sys.argv[2] == 'hostip') and \
(sys.argv[4] == '-u' or sys.argv[4] == 'user') and \
(sys.argv[6] == '-p' or sys.argv[6] == 'password') and \
len(sys.argv) == 8:
addinfo(sys.argv[3], sys.argv[5], sys.argv[7])
else:
raise ScriptError('argument error')
elif sys.argv[1] == 'delete':
if (sys.argv[2] == '-h' or sys.argv[2] == 'hostip') and len(sys.argv) == 4:
deleteinfo(sys.argv[3])
else:
raise ScriptError('argument error')
elif sys.argv[1] == 'list':
listinfo()
else: raise ScriptError('no such option')

if __name__ == '__main__':
main()
如果我的文章对你起到了帮助,你可以选择金额不限的捐助,帮助我写出更多的文章。