用python实现学生管理系统

学生管理系统

相信大家学各种语言的时候,练习总是会写各种管理系统吧,管理系统主要有对数据的增删查改操作,原理不难,适合作为练手的小程序

数据的结构

要保存数据就需要数据结构,比如c里面的结构体啊,python里面的列表,字典,还有类都是常用的数据类型
在这里,我使用了链表来作为学生数据的数据结构,
即 Node类 和 Student_LinkList类,来实现链表

数据的持久化

我们在程序中产生的数据是保存在内存中的,程序一旦退出,下次就不能恢复此次的数据了,因此需要把内存种的数据,保存到文件或数据库中,存储起来,这个过程就叫数据的持久化

本程序使用了python标准库pickle提供的序列化方法dump()和load()来实现数据的持久化

配置文件

使用配置文件,可以方便程序中使用不同的子类实现,

本程序使用configparser来对配置文件解析
本程序配置文件名为 Student.ini

    #Student.ini文件
    [Student]
    student = Student_LinkList
    
    [Persistence]
    persistence = Persistence_Pickle
    file = student.pik

类之间的关系

Student #和学生数据有关的抽象类
±- Student_LinkList
Persistence #和持久化有关的抽象类
±- Persistence_Pickle
MyConfigure #和配置文件读取有关的类
UI #和交互有关的父类
±- Cmd_UI

界面预览

源码

    '''
    使用单链表实现的学生管理系统
    '''
    import pickle
    import abc
    import configparser
    
    class Student(abc.ABC):
     '''
     抽象学生类
     '''
     @abc.abstractmethod
     def add(self):
     '''
     增加学生结点
     '''
     pass
    
     @abc.abstractmethod
     def ladd(self):
     '''
     从左侧增加学生结点
     '''
     pass
    
     @abc.abstractmethod
     def delete(self,id_):
     '''
     根据id值来删除一个结点
     '''
     pass
    
     @abc.abstractmethod
     def delete_name(self,name):
     '''
     根据姓名来删除一个结点
     '''
     pass
    
     @abc.abstractmethod
     def insert(self,idx,val):
     '''
     插入到指定的位置
     '''
     pass
    
     @abc.abstractmethod
     def show(self):
     '''
     显示所有的学生结点
     '''
     pass
    
     @abc.abstractmethod
     def search_id(self):
     '''
     根据id查询节点
     '''
     pass
    
     @abc.abstractmethod
     def search_name(self):
     '''
     根据name查询节点
     '''
    
     @abc.abstractmethod
     def modity_id(self):
     '''
     根据id找到节点,然后修改
     '''
     pass
    
    
    
    class Node(object):
     '''
     学生链表结点
     '''
     def __init__(self,id_: int,name: str,sex: str,age: int,score: int):
     self.id = id_
     self.name = name
     self.sex = sex
     self.age = age
     self.score = score
    
     self.next = None
    
     def modity(self,id_,name,sex,age,score):
     '''
     修改
     '''
     self.id = id_
     self.name = name
     self.sex = sex
     self.age = age
     self.score = score
    
    
     def __str__(self):
     '''
     用于显示输出
     '''
     return f"[学生:{self.id:^2}]-->name:{self.name:^10}sex:{self.sex:^10}age:{self.age:^10}score:{self.score:^10}"
    
    class Student_LinkList(Student):
     '''
     学生链表
     '''
     def __init__(self):
     self.head = Node(-1,'head','-1',-1,-1)
     self.length = 0
     self.tail = self.head #尾部结点用于尾插
    
     def add(self,id_,name,sex,age,score):
     '''
     添加一个学生结点,尾插
     '''
     #print('当前tail的值',self.tail)
     temp = Node(id_,name,sex,age,score)
     self.tail.next = temp 
     self.tail = self.tail.next
    
     self.length += 1
     print('[info]:添加成功')
    
     def ladd(self,id_,name,sex,age,score):
     '''
     添加一个学生,头插
     '''
     temp = Node(id_,name,sex,age,score)
     temp.next = self.head.next
     self.head.next = temp
    
     if self.tail == self.head:
      self.tail = temp
    
     self.length += 1
     print('[info]:添加成功')
    
     def delete(self,id_):
     '''
     根据id值来删除一个结点,用迭代实现
     '''
     p = self.head
     while p.next != None and p.next.id != id_:
      p = p.next
    
     if p.next == None:
      print('[error]:找不到id')
      return -1
     else:
      temp = p.next
      p.next = temp.next
      #如果删除的是尾结点,还要移动tail
      if temp.next == None:
      self.tail = p
      del temp
     print('[info]:删除成功')
    
     def delete_name(self,name):
     '''
     根据姓名来删除一个结点,用递归实现
     '''
     def _func(node: Node,name: str):
      '''
      递归函数
      '''
      #到了尾巴节点了,还没有找到
      if node.next == None:
      print('[info]:找不到name')
      return False
      elif node.next.name == name:
      temp = node.next
      node.next = temp.next
      #如果删除的是尾结点,还要移动tail
      if temp.next == None:
       self.tail = node
      del temp
      print('[info]:删除成功')
      return True
      else:
      return _func(node.next,name)
    
     t = self.head
     return _func(t,name)
    
     def insert(self,idx,id_,name,sex,age,score):
     '''
     在指定位置插入数据
     '''
     if idx > self.length or idx == 0:
      print(f'[error]:你输入的索引非法(1-{self.length})')
      return 0
     p,cur = self.head,0
     while p != None and cur < idx-1:
      p = p.next
    
     if cur < idx-1:
      return -1
     else:
      temp = Node(id_,name,sex,age,score)
      temp.next = p.next
      p.next = temp
      return True
     print('[info]:插入成功')
    
     def search_id(self,id_):
     '''
     根据id查询节点
     '''
     p = self.head
     while p != None and p.id != id_:
      p = p.next
     if p == None:
      return -1
     else:
      return p
    
     def search_name(self,name):
     '''
     根据name查询节点
     '''
     p = self.head
     
     def _func(node: Node,name: str):
      '''
      递归函数
      '''
      if node == None:
      return -1
      elif node.name == name:
      return node
      return _func(node.next,name)
    
     return _func(p,name)
    
     def modity_id(self,id0,id_,name,sex,age,score):
     '''
     根据id找到节点,然后修改
     '''
     node = self.search_id(id0)
     if node == -1:
      print('[error]:找不到该id')
      return -1
     else:
      node.modity(id_,name,sex,age,score)
    
    
     def show(self):
     '''
     显示所有的学生结点,迭代
     '''
     print(f'\n{"-"*25}以下是系统内数据{"-"*25}')
     temp = []
     p = self.head
     while p != None:
      temp.append(p)
      p = p.next
     return temp
    
    class Student_Array():
     '''
     用数组实现学生数据存储
     '''
     pass
    
    class Student_Queue():
     '''
     用队列实现
     '''
     pass
    
    class Student_Dict():
     '''
     用队列实现
     '''
     pass
    
    class Persistence(abc.ABC):
     '''
     链表数据的持久化
     '''
     @abc.abstractmethod
     def save(self):
     '''
     把对象保存
     '''
     pass
    
     @abc.abstractmethod
     def load(self):
     '''
     加载对象
     '''
     pass
    
    class Persistence_Pickle(Persistence):
     '''
     使用pickle来序列化
     '''
     def __init__(self,cls: Student,file_):
     self.filename = file_
     self.obj = None
     self.cls = cls
    
     def save(self):
     with open(self.filename,'wb') as f:
      pickle.dump(self.obj,f)
    
     def load(self):
     try:
      with open(self.filename,'rb') as f:
      temp = pickle.load(f)
     except:
      temp = globals()[self.cls]()
     print('返回temp:',type(temp))
     self.obj = temp
     return temp
    
    class Persistence_File(Persistence):
     '''
     使用文件来持久化
     '''
     pass
    
    class Persistence_Mysql(Persistence):
     '''
     使用Mysql数据库来持久化
     '''
     pass
    
    class Persistence_Socket(Persistence):
     '''
     使用远程套接字持久化
     '''
     pass
    
    class MyConfigure(object):
     '''
     用来读取配置文件的类
     '''
     def __init__(self):
     self.config = configparser.ConfigParser()
    
     def save(self):
     '''
     保存配置文件
     '''
     with open('Student.ini','w') as f:
      self.config.write(f)
    
     def load(self):
     '''
     加载配置文件
     '''
     self.config.read('Student.ini')
    
     def get_student_class(self):
     '''
     获得Student该使用哪个子类
     '''
     return self.config['Student']['student']
    
     def get_persistence_class(self):
     '''
     获得持久化,该使用那个类,
     如果是Pickle或文件,还有file作为保存的文件名
     '''
     temp = {}
     temp['persistence'] = self.config['Persistence']['persistence']
     if 'Persistence_Pickle' in temp['persistence']:
      temp['file'] = self.config['Persistence']['file']
     return temp
    
    class UI(object):
     '''
     界面交互
     '''
     def __init__(self):
     self.config = MyConfigure()
     self.config.load()
     s_class = self.config.get_student_class()
     p_class = self.config.get_persistence_class()
    
     self.persistence = globals()[p_class['persistence']](s_class,p_class['file'])
     self.student = self.persistence.load()
     print('实例化成功:',self.student,self.persistence)
    
     def save(self):
     '''
     把数据保存
     '''
     self.persistence.save()
    
     def quit(self):
     '''
     退出:先保存配置,然后退出
     '''
     self.config.save()
     self.save()
    
     def _show(self):
     '''
     显示所有学生节点
     '''
     return self.student.show()
    
    
     def _add(self,direction,*temp):
     '''
     增加学生结点,
     direction 1左添加,2右添加
     '''
     if direction == 1:
      self.student.ladd(*temp)
     elif direction == 2:
      self.student.add(*temp)
    
     def _delete(self,attribute: int,val: str):
     '''
     删除学生节点
     attribute: 需要根据哪个属性删除,1.id 或 2.name
     '''
     if attribute == 1:
      self.student.delete(val)
     elif attribute == 2:
      self.student.delete_name(val)
    
     def _insert(self,idx,*temp):
     '''
     把学生节点插入到指定的位置
     '''
     self.student.insert(idx,*temp)
    
     def _search(self,attribute,val):
     '''
     查询
     '''
     if attribute == 1:
      return self.student.search_id(val)
     elif attribute == 2:
      return self.student.search_name(val)
    
     def _modity(self,attribute,id_,*temp):
     '''
     修改
     '''
     if attribute == 1:
      self.student.modity_id(id_,*temp)
     elif attribute == 2:
      print('[info]:因为没实现,所以什么也不做')
      pass #根据name修改没有写
    
    
    
    
    class Cmd_UI(UI):
     '''
     命令行的交互界面
     '''
     def __init__(self):
     super(Cmd_UI,self).__init__()
    
     def get_input_1_2(self,info: str):
     '''
     获得输入,返回1或者2
     info: 描述输入的信息
     '''
     x = None
     while x == None:
      temp = input(info)
      if temp == '1':
      x = 1
      elif temp == '2':
      x = 2
      else:
      print('你只能输入1或者2')
     return x
    
     def get_input_arg(self):
     '''
     获得用户的输入构造学生节点
     '''
     id_ = input('请输入id')
     name = input('请输入姓名')
     sex = input('请输入性别')
     age = input('请输入年龄')
     score = input('请输入成绩')
     return (id_,name,sex,age,score)
    
     def delete(self):
     '''
     删除节点
     '''
     info = '你想要根据哪个属性删除节点:1.id 2.name'
     attribute = self.get_input_1_2(info)
     val = input('输入你想要删除的值:')
     self._delete(attribute,val)
    
     def show(self):
     '''
     显示
     '''
     rel = self._show()
     for i in rel:
      print(i)
    
     def add(self):
     '''
     增加学生结点
     '''
     info = '你想要插入的位置:1.左边 2.右边'
     direction = self.get_input_1_2(info)
     arg = self.get_input_arg()
     self._add(direction,*arg)
    
     def insert(self):
     '''
     新学生,插入到指定的位置
     '''
     idx = int(input('输入要插入的位置'))
     temp = self.get_input_arg()
     self._insert(idx,*temp)
    
     def search(self):
     '''
     查询学生
     '''
     info = '你想要根据哪个属性搜索节点:1.id 2.name'
     attribute = self.get_input_1_2(info)
     val = input('输入你想要查询的值:')
    
     print(self._search(attribute,val))
    
     def modity(self):
     '''
     修改学生信息
     '''
     info = '你想要根据哪个属性搜索节点:1.id 2.name'
     attribute = self.get_input_1_2(info)
     val_ = input('输入要查询的值:')
     temp = self.get_input_arg()
     self._modity(attribute,val_,*temp)
    
     def main(self):
     '''
     主流程
     '''
     info = '''
     *******************
     *kalpa学生管理系统*
     * 0.显示数据 *
     * 1.增加数据 *
     * 2.删除数据 *
     * 3.查询数据 *
     * 4.修改数据 *
     * 5.保存并退出 *
     *******************
     '''
     print(info)
     a = '0'
     while a in ['0','1','2','3','4','5']:
      if a == '0':
      self.show()
      elif a == '1':
      self.add()
      elif a == '2':
      self.delete()
      elif a == '3':
      self.search()
      elif a == '4':
      self.modity()
      elif a == '5':
      self.quit()
      return
      a = input('>>')
    
    
    if __name__ == "__main__":
     ui = Cmd_UI()
     ui.main()

关于管理系统的更多内容请点击 《管理系统专题》 进行学习

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

在这里插入图片描述

posted @ 2021-06-21 18:09  老酱  阅读(600)  评论(0编辑  收藏  举报