简介
本次作业继承于上一次的交互问题(用户屏幕输入输出),额外内容为文件在硬盘上的读取与存储.是为了之后的简易版本的自然语言处理任务做铺垫.
题目
"""
本次的问题很简单,文件读取,与,简单的人机交互,以及异常处理
答题程序
特殊要求,问题一共十个,问题和回答都需要存储到硬盘中(最起码保留一次),并可以计算分数.
提示:open操作 + 自定义解析器,或者使用numpy,或者pandas的保存功能.
交卷时间:2017/10/31/ 10:50
问题分析:我们可以问题分解将原问题简单化
首先是原问题可分解为硬盘读入内存,程序人机交互,内存写入硬盘.
那么问题也就分解为了 人机交互部分 与 硬盘读取写入操作
"""
问题分解
这次与之前的内容不同之处就在于,我们这一次将开发一个完整的程序.相信对于大一的萌新的这恐怕是第一次.
那么在这个问题中,你们首先会面对什么问题呢?首先是问题的复杂性,第一眼看上去这确实是一个复杂的程序.那么面对复杂的程序我们应该怎么办呢?
我们应该做的就是将复杂问题简单化,复杂问题简单化一般有两种常用措施:第一,问题分解,将复杂性问题分解为数个简单问题,第二,问题转化,将复杂问题转化为简单问题.对于这个工程而言,第二种方法是难以实现的,很难从问题转化的角度进行复杂问题简单化.我们首先应该考虑的是第一个方案,问题拆分.
分解问题
这个问题如何分解,首先从技术角度来看,我们之前已经使用过简单的人机交互x = input("请在屏幕上输入文字")
,在昨天的试卷答案中,我们已经给出了该语法,将屏幕输入的文字存储为字符串变量.
那么也就是说,我们已经可以获取用户输入的字符串变量,并存储在内存中.然后这个时候我们可以考虑其他我们没有编写过得部分,第一计算分数,第二存储到硬盘.
第一个计算分数,我们要做的是用户的回答是否与我们的答案一致,那么在我们常接触的试卷中?有什么问题是可以利用我们已有的知识直接进行处理的呢?那肯定是有标准答案的判断题,选择题,以及答案唯一的填空题.此处我选择填空题两个,选择题一个编写示例程序
第二个是硬盘存储,提示关键词是 open() ,既然给了关键词只需要直接百度 python open 即可,很多教程写的非常清楚.亦或者是登陆我之前给说的python网站去查找相应api.对应部分为python3 file
文件操作.
编程
获取用户输入,并将其存储到list中,当然用十个变量也可以
# # 首先是最简单的人机交互
# # 问题既可以使用十个变量进行存储也可以使用list进行存储.
question = ["问题一", "问题二"]
answer = input(question[0] + '
')
# # 同样,我们也可以使用list存储答案
answer_list = []
answer_list.append(answer)
不过还有更好的实现方式for循环,顺便以同样的方式打印出来,检查一下
# 更好的代码实现方式
for i in question: answer_list.append(input(i + "
"))
# 打印问题与答案,进行人工检查
for i in range(len(question)): print(question[i], '
', answer_list[i], '
')
计算分数的问题
# 计算分数的问题,需要问题与答案有一定的格式
# 比如
question = ["1+1 = ?", "2+2 =?", "下列最大的水果是:1,西瓜,2,苹果"]
key1 = ["2", "4", "1"]
key1_test = [2, "4", "1"]
key2 = [2, 4, "1"]
# 要注意链表中每个元素的数据类型,不同的数据类型除了布尔类型判断时可以进行自动转换外,其他变量并没有该功能
#所以对于计算题而言,必须将input方法返回的str变量转化为与答案一致的变量类型才行.
#当然反之依然,我们需要的仅仅是让他们的类型一致,以便进行判断.
# 转化代码如下:
for i in question: answer_list.append(int(input(i + "
")))
# 此时我们就可以改卷子了,使用for循环进行判断,顺便封装以便调用
def GetScore(key, answer):
Score = 0
for i in range(len(key)):
if int(key[i]) == int(answer[i]): # 注意此处判断条件,int?str?或者赋予回答与答案一样的数据类型.
Score += 1
return Score
print(GetScore(key1, key1_test)) # 在屏幕输出成绩
第三个问题,python中的文件操作
本出我们使用的是python中的文件操作,open方法.
因为之前我们存储问题,用户回答,以及答案的变量都市list,而list在open操作中的行写入或者行读取,存在一定问题,我们这里直接使用list==>str,与str===>list的方式进行硬盘到内存的读写与转换.
方法如下:
# 存储
file = open(file="/home/fonttian/Data/17_DS_AI/open_file.txt", mode="w")
file.write(" ".join(key1))
# file.write(str(key1))
file.close()
# 读取
file = open(file="/home/fonttian/Data/17_DS_AI/open_file.txt", mode="r")
key_str = file.read()
file.close()
key_list = key_str.split(" ")
print(key_list) # 输出
但是以上的代码存在两个明显的不足之处,第一list与str转化过程中使用的分个符号是” “,空格,而空格可能存在于我们的问题或者用户答案中,所以我们需要使用更难被使用的分隔符号,比如六个星号"******"
同时为了避免用户在答案中使用六个星号,我们在读取数据后,可以在增加一个过滤字符串的操作,(除去六个星号).(过滤字符串请参考正则表达式部分)
第二个问题是,python中用更好的文件操作的方式,with,利用with我们可以自动关闭文件IO流,增加了安全性,减少了代码量,同时也让代码更加结构化.
如同之前的提示:使用其他类库也是可以的:
# 利用第三方类库
import numpy as np
np_key1 = np.array([int(i) for i in key1])
print(np_key1)
np.savetxt("/home/fonttian/Data/17_DS_AI/np_key1.txt", np_key1)
np_key1 = np.loadtxt("/home/fonttian/Data/17_DS_AI/np_key1.txt")
print(np_key1) # 格式转化为 np.float
封装代码
# 封装
def GetScore_Examples(key, answer):
Score = 0
for i in range(len(key)):
if int(key[i]) == int(answer[i]): # 注意此处判断条件,int?str?或者赋予回答与答案一样的数据类型.
Score += 1
return Score
def FileIO_Examples(filename, list=None, save=False):
if save == False:
with open(file=filename, mode="r") as file:
return file.read().split("******")
else:
with open(file=filename, mode="w") as file:
file.write("******".join(list))
def Main_Examples():
question = FileIO_Examples("/home/fonttian/Data/17_DS_AI/question.txt", save=False)
key1 = FileIO_Examples("/home/fonttian/Data/17_DS_AI/key1.txt", save=False)
answer_list = []
for i in question: answer_list.append(input(i + "
"))
score = GetScore_Examples(key1, answer_list)
print("your score :", score)
FileIO_Examples(filename="/home/fonttian/Data/17_DS_AI/answer_list.txt", list=answer_list, save=True)
Main_Examples()