Python知识点串连(四)

我们学了过面向对象,下面,我们通过成绩单程序来展示面向对象编程的应用。

8,python 面向对象编程

先来分析一下,在这个程序中,哪些地方可以用类来表示。之前我们曾经使用字典来保存每位学生的信息,现在可以定义一个 Student 类来表示学生,并用这个类的属性来表示姓名、学号和成绩等信息。我们还可以用 Student 类的一个方法来计算并显示总成绩,甚至还可以使用类的方法来打印学生。

先来看一下这个类包含哪些属性和方法。使用构造方法初始化属性的值。属性有表示姓名的 name,表示学号的 ID,表示语文成绩的 score1,表示数学成绩的 score2,表示英语成绩的 score3,表示总成绩的 total。

然后定义了 getSum() 方法,它用来计算总分。这个方法将表示语文成绩、数学成绩和英语成绩的属性 score1、score2 和 score3 的值加起来,将结果赋值给属性 total。

还定义了 printStudent 方法,它会将属性拼接成一个字符串并打印出来。

Student 类的详细代码如下所示。
#Student类来表示学生
class Student:
    #使用构造方法初始化属性的值
    def __init__(self):
        self.name = ""
        self.ID =""
        self.score1 = 0
        self.score2 = 0
        self.score3 = 0
        self.total = 0

    #计算总分
    def getSum(self):
        self.total=self.score1 + self.score2 + self.score3

    #将属性拼接成一个字符串并打印出来
    def printStudent(self):
        print(self.ID,"\t",self.name,"\t",self.score1,"\t",self.score2,"\t",self.score3,"\t",self.total)
 
下面是程序的其他部分,这里把涉及调用 Student 类的代码都突出显示出来。因为这些代码和上一章中用到的代码基本是一样的,这里就不再赘述。请读者留意其中突出显示的部分,可以看到,通过调用类的方法,也可以实现同样的功能,而且代码更加简洁,可复用性也更好。
#判断成绩列表中是否已经包含了学号,sList表示成绩列表,sID表示学号
def hasRecord(sList,sID):
    result=-1
    i = 0 
    for temp in sList:
       if temp.ID == sID:
            result=i
            break
       else:
           i=i+1
    return result

#判断输入成绩是否有效,subject表示科目,action表示进行操作
def getScore(subject,action):
    try:
        score=float(input("请输入"+subject+"成绩:"))
    except:
        print ("输入的不是数字,"+action+"失败!")
        return -1  

    if score <= 100 and score >= 0 :
        return score
    else:
        print ("输入的"+subject+"成绩有错误,"+action+"失败!")
        return -1

#显示功能列表,提示用户如何选择功能
def showInfo():
    print("-"*30)
    print(" 学生成绩系统 ")
    print(" 1.添加学生的信息")
    print(" 2.删除学生的信息")
    print(" 3.修改学生的信息")
    print(" 4.查询学生的信息")
    print(" 5.列出所有学生的信息")
    print(" 6.退出系统")
    print("-"*30)

def updateStudent(student):
    while True:
        try:
            alterNum=int(input(" 1.修改姓名\n 2.修改学号 \n 3.修改语文成绩 \n 4.修改数学成绩 \n 5.修改英语成绩 \n 6.退出修改\n"))
        except:
            print ("输入有误,请输入编号1到6")
            continue

       if alterNum == 1: #修改姓名
            newName=input("输入更改后的姓名:")
            student.name = newName
            print("姓名修改成功")
            break
        elif alterNum == 2: #修改学号
            newId=input("输入更改后的学号:")
            newIndex=hasRecord(studentList,newId)
            if newIndex>-1:
                print("输入学号不可重复,修改失败!")
            else:                                  
                student.ID=newId
                print("学号修改成功")
            break
        elif alterNum == 3: #修改语文成绩
            score1=getScore("语文","修改")
            if score1 >-1:              
                student.score1=score1
                student.getSum()
                print ("语文成绩修改成功!")
            break
        elif alterNum == 4: #修改数学成绩
            score2=getScore("数学","修改")
            if score2 >-1:
                student.score2=score2
                student.getSum()
                print ("数学成绩修改成功!")
            break
        elif alterNum == 5: #修改英语成绩
            score3=getScore("英语","修改")
            if score3 >-1:
                student.score3=score3
                student.getSum()
                print ("英语成绩修改成功!")
            break                
        elif alterNum == 6: #退出修改
            break
        else: #输入了错误的数字
            print("输入错误请重新输入")

studentList=[] 
while True:
    showInfo()   

    try:        
        key = int(input("请选择功能(输入序号1到6):"))
    except: #如果出现异常,跳出本次循环
        print("您的输入有误,请输入序号1到6")
        continue 

    if key == 1: #添加学生信息
        print("您选择了添加学生信息功能")
        name = input("请输入姓名:")
        stuId = input("请输入学号(不可重复):")
        index=hasRecord(studentList,stuId)       
        if index >-1:
            print("输入学号重复,添加失败!")
            continue
        else:
            newStudent = Student()
            newStudent.name = name
            newStudent.ID = stuId
            score1=getScore("语文","添加")
            if score1 >-1:              
                newStudent.score1=score1
            else:
                continue           

            score2=getScore("数学","添加")
            if score2 >-1:
                newStudent.score2=score2
            else:
                continue
            score3=getScore("英语","添加")
            if score3 >-1:       
                newStudent.score3=score3
            else:
                continue                      

            newStudent.getSum()
            studentList.append(newStudent)
            print (newStudent.name +"的成绩录入成功!")

    elif key == 2:  #删除学生信息
        print("您选择了删除学生信息功能")
        stuId=input("请输入要删除的学号:")
        index=hasRecord(studentList,stuId)
        if index>-1:
            del studentList[index]
            print("删除成功!")           
        else:
            print("没有此学生学号,删除失败!")

    elif key == 3: #修改学生信息
        print("您选择了修改学生信息功能")
        stuId=input("请输入你要修改学生的学号:")
        index=hasRecord(studentList,stuId)       
        if index == -1:
            print("没有此学号,修改失败!")
        else:
            temp=studentList[index]
            updateStudent(temp)

    elif key == 4: #查询某位学生信息
        print("您选择了查询学生信息功能")
        stuId=input("请输入你要查询学生的学号:")
        index=hasRecord(studentList,stuId)
        if index == -1:
            print("没有此学生学号,查询失败!")
        else:
            temp=studentList[index]
            print (" 学号\t姓名\t语文\t数学\t英语\t总分")
            temp.printStudent()

    elif key == 5:             
        print("接下来进行遍历所有的学生信息...")
        print(" 学号\t姓名\t语文\t数学\t英语\t总分")
        for temp in studentList:
           temp.printStudent() 

    elif key == 6:       
        quitConfirm = input("确认要退出系统吗 (Y或者N)?")
        if quitConfirm.upper()=="Y":
            print("欢迎使用本系统,谢谢")
            break

    else: #没有正确输入编号
        print("您输入有误,请重新输入")

9,python文件的打开,写入和读取

我们在前面编写过成绩单的程序,其中,成绩单中的信息只能在程序运行时存在,当关闭程序后,这些信息就全部丢失了,这显然无法满足用户的需求。

对于这种情况,我们就可以把这些信息存储到一个文本文件中。这样,无论程序是否关闭,都不会丢失数据了;而且还可以把这个文本文件拷贝到任意的计算机上,学生的信息都仍然会存在。

接下来,我们看一下具体的实现方法。首先我们会在“成绩单.py”这个文件的同级目录下创建一个 students.txt 文本文件。因为这个文本文件和我们运行的程序是在同级目录下,所以不需要指定路径就可以找到这个文件。

然后,我们会增加 3 个新的自定义函数:分别是从文本中读取数据的 LoadFromText() 函数、向文本中添加数据的 AddToText() 函数和把列表信息写入到文本的 WriteToText() 函数。

从文本中读取数据的 LoadFromText() 函数会接受一个列表参数,其目的是将文本文件中的内容填充到这个列表中。这个函数首先会在屏幕上打印一条提示信息,表示要从文本中加载已有信息。然后调用 open() 函数,以只读模式打开“students.txt”文件,并且创建文件对象 txtFile。

然后使用条件为 True 的一个 while 循环,表示这个循环会一直运行,直到满足特定条件后,执行循环中的 break 语句,才能跳出循环。

在循环中,调用 readline() 函数读取一行文本并且赋值给变量 line。然后判断 line 是否为空或空字符串,如果满足条件,表示到达了文件的末尾,就跳出循环;否则,调用 split() 方法,以“ ”(两个空格)作为分隔符,将结果赋值给列表 s。

然后创建 Student 类的一个实例 stu,将 s 中的内容赋值给 stu 的各个属性,然后调用 append() 函数把 stu 实例添加到 sList 列表中。我们之前介绍过字符串和列表相互转换时曾经介绍过 split() 方法。while 循环结束后,调用 close() 函数关闭文件。
 
#调用文件中保存的数据
def LoadFromText(sList): 
    print ("加载已有数据......")
    try:
        txtFile = open("students.txt", "r")

        while True:
            line=txtFile.readline()
            if not line or line.strip()=="" :
                break
            else:           
                s = line.split(" ")
                stu = Student()
                stu.ID = s[0]
                stu.name = s[1]
                stu.score1 = float(s[2])
                stu.score2 = float(s[3])
                stu.score3 = float(s[4])
                stu.total = float(s[5])
                sList.append(stu)
    except: #如果不存在student.txt,创建这个文本文件
        txtFile = open("students.txt", "w")
       
    txtFile.close()
    print ("加载成功!")
 
向文本中添加数据的AddToText ()函数会接受一个Student类的实例stu作参数。首先调用open()函数,以添加模式打开“students.txt”文件,并且创建文件对象txtFile。然后把stu的各个属性值写入到文本对象中,并且在每个属性之间放入两个空格做间隔。在末尾会加入一个“\n”,表示换行。最后,调用close()函数关闭文件。
#新增一条数据到文件中
def AddToText(stu):
    txtFile = open("students.txt", "a")
    txtFile.write(stu.ID)
    txtFile.write(" ")
    txtFile.write(stu.name)
    txtFile.write(" ")
    txtFile.write(str(stu.score1))
    txtFile.write(" ")
    txtFile.write(str(stu.score2))
    txtFile.write(" ")
    txtFile.write(str(stu.score3))
    txtFile.write(" ")
    txtFile.write(str(stu.total))
    txtFile.write("\n")
    txtFile.close()

向文本中写入数据的 WriteToText () 函数会接受一个列表参数,其目的是将列表中的数据写入到文本文件中。首先调用 open() 函数,以写入模式打开“students.txt”文件,并且创建文件对象 txtFile。

然后使用一个 for 循环,遍历 sList 列表中的各个元素,把每个元素赋值给 Student 类的实例 stu。然后把 stu 的各个属性值写入到文本中,并且在每个属性之间放入两个空格做间隔。在末尾会加入一个“\n”,表示换行。循环结束后,调用 close() 函数关闭文件。
#将列表中全部数据保存到文件中
def WriteToText(sList):
    txtFile = open("students.txt", "w")
    for stu in sList:       
        txtFile.write(stu.ID)
        txtFile.write(" ")
        txtFile.write(stu.name)
        txtFile.write(" ")
        txtFile.write(str(stu.score1))
        txtFile.write(" ")
        txtFile.write(str(stu.score2))
        txtFile.write(" ")
        txtFile.write(str(stu.score3))
        txtFile.write(" ")
        txtFile.write(str(stu.total))
        txtFile.write("\n")
    txtFile.close()

下面是程序的其他部分,我们把涉及调用这 3 个函数的代码突出显示出来。因为其他代码和上节中的代码基本一致,这里就不再赘述。
#定义Student类来表示学生
class Student:
    #使用构造方法初始化属性的值
    def __init__(self):
        self.name = ""
        self.ID =""
        self.score1 = 0
        self.score2 = 0
        self.score3 = 0
        self.total = 0

    #计算总分
    def getSum(self):
        self.total=self.score1 + self.score2 + self.score3

    #将属性拼接成一个字符串并打印出来
    def printStudent(self):   
        print(self.ID,"\t",self.name,"\t",self.score1,"\t",self.score2,"\t", self.score3,"\t",self.total)

#判断成绩列表中是否已经包含了学号,sList表示成绩列表,sID表示学号
def hasRecord(sList,sID):
    result=-1
    i = 0 
    for temp in sList:
        if temp.ID == sID:
             result=i
             break
        else:
            i=i+1
    return result

#判断输入成绩是否有效,subject表示科目,action表示进行操作
def getScore(subject,action):
    try:
      score=float(input("请输入"+subject+"成绩:"))           
    except:
        print ("输入的不是数字,"+action+"失败!")
        return -1  

    if score <= 100 and score >= 0 :
        return score
    else:
        print ("输入的"+subject+"成绩有错误,"+action+"失败!")
        return -1

#显示功能列表,提示用户如何选择功能
def showInfo():
    print("-"*30)
    print(" 学生成绩系统 ")
    print(" 1.添加学生的信息")
    print(" 2.删除学生的信息")
    print(" 3.修改学生的信息")
    print(" 4.查询学生的信息")
    print(" 5.列出所有学生的信息")
    print(" 6.退出系统")
    print("-"*30)

def updateStudent(sList,student):
    while True:      
        try:
            alterNum=int(input(" 1.修改姓名\n 2.修改学号 \n 3.修改语文成绩 \n 4.修改数学成绩 \n 5.修改英语成绩 \n 6.退出修改\n"))
        except:
            print ("输入有误,请输入编号1到6")                   
        continue

        if alterNum == 1: #修改姓名
            newName=input("输入更改后的姓名:")
            student.name = newName           
            print("姓名修改成功")
            break
        elif alterNum == 2: #修改学号
            newId=input("输入更改后的学号:")
            newIndex=hasRecord(sList,newId)
            if newIndex>-1:
                print("输入学号不可重复,修改失败!")
            else:                                  
                student.ID=newId
                print("学号修改成功")
            break
        elif alterNum == 3: #修改语文成绩
            score1=getScore("语文","修改")
            if score1 >-1:              
                student.score1=score1
                student.getSum()              
                print ("语文成绩修改成功!")                  
            break
        elif alterNum == 4: #修改数学成绩
            score2=getScore("数学","修改")
            if score2 >-1:
                student.score2=score2
                student.getSum()                
                print ("数学成绩修改成功!")                  
            break
        elif alterNum == 5: #修改英语成绩
            score3=getScore("英语","修改")
            if score3 >-1:
                student.score3=score3
                student.getSum()                 
                print ("英语成绩修改成功!")                  
            break                
        elif alterNum == 6: #退出修改
            break
        else: #输入了错误的数字
            print("输入错误请重新输入")
    WriteToText(sList)

studentList=[] 
LoadFromText(studentList)
while True:
    showInfo()   

    try:        
        key = int(input("请选择功能(输入序号1到6):"))
    except: #如果出现异常,跳出本次循环
        print("您的输入有误,请输入序号1到6")
        continue 

    if key == 1: #添加学生信息
        print("您选择了添加学生信息功能")
        name = input("请输入姓名:")
        stuId = input("请输入学号(不可重复):")
        index=hasRecord(studentList,stuId)       
        if index >-1:
            print("输入学号重复,添加失败!")
            continue
        else:
            newStudent = Student()
            newStudent.name = name
            newStudent.ID = stuId

            score1=getScore("语文","添加")
            if score1 >-1:               
                newStudent.score1=score1
            else:
                continue           

            score2=getScore("数学","添加")
            if score2 >-1:
                newStudent.score2=score2
            else:
                continue

            score3=getScore("英语","添加")
            if score3 >-1:       
                newStudent.score3=score3
            else:
                continue 
            newStudent.getSum()
            studentList.append(newStudent)
            AddToText(newStudent)
            print (newStudent.name +"的成绩录入成功!")

    elif key == 2:  #删除学生信息
        print("您选择了删除学生信息功能")
        stuId=input("请输入要删除的学号:")
        index=hasRecord(studentList,stuId)       
        if index>-1:
            del studentList[index]
            WriteToText(studentList)
            print("删除成功!")           
        else:
            print("没有此学生学号,删除失败!")

    elif key == 3: #修改学生信息
        print("您选择了修改学生信息功能")
        stuId=input("请输入你要修改学生的学号:")
        index=hasRecord(studentList,stuId)       
        if index == -1:
            print("没有此学号,修改失败!")
        else:
            temp=studentList[index]
            updateStudent(studentList,temp)

    elif key == 4: #查询某位学生信息
        print("您选择了查询学生信息功能")
        stuId=input("请输入你要查询学生的学号:")
        index=hasRecord(studentList,stuId)
        if index == -1:
            print("没有此学生学号,查询失败!")
        else:
            temp=studentList[index]
            print (" 学号\t姓名\t语文\t数学\t英语\t总分")
            temp.printStudent()      

    elif key == 5:  #打印出所有学生的信息           
        print("接下来进行遍历所有的学生信息...")
        print(" 学号\t姓名\t语文\t数学\t英语\t总分")
        for temp in studentList:       
            temp.printStudent() 
    elif key == 6:  #选择退出系统     
        quitConfirm = input("确认要退出系统吗 (Y或者N)?")
        if quitConfirm.upper()=="Y":
            print("欢迎使用本系统,谢谢")
            break

    else: #没有正确输入编号
        print("您输入有误,请重新输入")

录入完学生的信息后,即使关闭程序,也可以在“students.txt”文件中看到这些录入的信息,如下图所示。

Python 文件的打开,读取和写入
 
到此我们把一些能成绩单串连的知识点已经串连完成,没有回顾到的,就要自己翻看了。