1. 程式人生 > >面向對象之選課系統

面向對象之選課系統

文件 NPU 情況 屬性 新的 ati erro brush light

import os
import sys
import pickle

student_info = ‘student_info‘
course_info = ‘course_info‘
userinfo = ‘userinfo‘
class Base:
    def __str__(self):
        return self.name
class Course(Base):
    def __init__(self,name,price,period,teacher):
        self.name = name
        self.price = price
        self.period = period
        self.teacher = teacher
    def __repr__(self):
        return ‘ ‘.join([self.name, self.price, self.period, self.teacher])

class Person:
    @staticmethod
    def get_from_pickle(path):
        with open(path,‘rb‘) as f:
            while True:
                try :
                    stu_obj = pickle.load(f)
                    yield stu_obj  #防止全部讀出、內存消耗過大  生成器
                except EOFError:
                    break

    def show_courses(self):
        for count,course in enumerate(self.get_from_pickle(course_info),1):
            print(count,repr(course))

    def dump_obj(self,path,obj):
        with open(path,‘ab‘) as f:
            pickle.dump(obj,f)





class Student(Person,Base):
    operate_lst = [
                   (‘查看所有課程‘, ‘show_courses‘),
                   (‘選擇課程‘, ‘select_course‘),
                   (‘查看已選課程‘, ‘check_selected_course‘),
                   (‘退出‘, ‘exit‘)]
    def __init__(self,name):
        self.name = name
        self.courses = []

    def __repr__(self):
        # course_name = [course.name for course in self.courses]
        course_name = [str(course) for course in self.courses]
        return ‘%s %s‘%(self.name,‘所選課程%s‘ % ‘|‘.join(course_name))

    def select_course(self):
        self.show_courses()
        num = int(input(‘num >>>‘))
        for count,course in enumerate(self.get_from_pickle(course_info),1):
            if count == num:
                self.courses.append(course)
                print(‘您選擇了%s課程‘ % (course))
                break
        else:print(‘沒有您要找的課程‘)

    def check_selected_course(self):
        for course in self.courses:
            print(course.name,course.teacher)

    def exit(self):
        #避免頻繁操作文件  退出之前一次修改
        with open(student_info+‘_bak‘, ‘wb‘) as f2:
            for stu in self.get_from_pickle(student_info):
                if stu.name == self.name:  # 如果從原文件找到了學生對象和我當前的對象是一個名字,就認為是一個人
                    pickle.dump(self, f2)  # 應該把現在新的學生對象寫到文件中
                else:
                    pickle.dump(stu, f2)  # 反之,應該原封不動的把學生對象寫回f2
        os.remove(student_info)
        os.rename(student_info+‘_bak‘,student_info)
        exit()

    @classmethod  #類方法
    def init(cls,name):
        for stu in cls.get_from_pickle(student_info):
            if stu.name == name:
                return stu
        else:print(‘沒有這個學生‘)

class Manager(Person):
    operate_lst = [(‘創建課程‘,‘create_course‘),
                   (‘創建學生‘,‘create_student‘),
                   (‘查看所有課程‘,‘show_courses‘),
                   (‘查看所有學生‘,‘show_students‘),
                   (‘查看所有學生的選課情況‘,‘show_student_course‘),
                   (‘退出‘,‘exit‘)]
    def __init__(self,name):
        self.name = name

    def create_course(self):
        name = input(‘course name : ‘)
        price = input(‘course price : ‘)
        period = input(‘course period : ‘)
        teacher = input(‘course teacher : ‘)
        course_obj = Course(name,price,period,teacher)
        self.dump_obj(course_info, course_obj)  #調用父類Person的方法  (問題:未判斷,創建的該對象是否存在)
        print(‘%s課程創建成功‘%course_obj.name)

    def create_student(self):
        # 用戶名和密碼記錄到userinfo文件,將學生對象存儲在student_info文件
        stu_name =input(‘student name : ‘)
        stu_pwd =input(‘student password : ‘)
        stu_auth = ‘%s|%s|Student\n‘%(stu_name,stu_pwd)
        stu_obj = Student(stu_name)
        with open(userinfo,‘a‘,encoding=‘utf-8‘) as f:
            f.write(stu_auth)  #存入userinfo表
        self.dump_obj(student_info, stu_obj) #調用父類Person的方法  (問題:未判斷,創建的該對象是否存在)
        print(‘%s學生創建成功‘%stu_obj.name)

    def show_students(self):
        for count,stu in enumerate(self.get_from_pickle(student_info),1):
            print(count,stu)  #Student類的實例對象 print() 會按照 繼承類Base  __str__的格式輸出

    def show_student_course(self):
        for stu in self.get_from_pickle(student_info):
            print(repr(stu))  #Student類的實例對象 print() 會按照 __repr__的格式輸入
            # print(stu)  默認是Student類的實例對象 print() 會按照 繼承類Base  __str__的格式輸出

    def exit(self):
        exit()

    @classmethod #類方法
    def init(cls,name):
        return cls(name)   # 管理員的對象  返回管理員實例對象

def login():
    name = input(‘username : ‘)
    pawd = input(‘password : ‘)
    with open(userinfo,encoding=‘utf-8‘) as f:
        for line in f:
            usr,pwd,identify = line.strip().split(‘|‘)
            if usr == name and pawd == pwd:
                return {‘result‘:True,‘name‘:name,‘id‘:identify}
        else:
            return {‘result‘:False,‘name‘:name}



ret = login()
if ret[‘result‘]:
    print(‘\033[1;32;40m登錄成功\033[0m‘)#sys.modules[__name__]有時我們需要將一個文件的信息(類、函數及變量)保存到文件,我們不能直接保存函數對象,而是將其轉化為fn.__name__
    if hasattr(sys.modules[__name__],ret[‘id‘]):  # hasattr(object, name) 判斷一個對象裏面是否有name屬性或者name方法,返回BOOL值,有name特性返回True, 否則返回False。
        cls = getattr(sys.modules[__name__],ret[‘id‘])#getattr(object, name[,default])獲取對象object的屬性或者方法,如果存在打印出來,如果不存在,打印出默認值,默認值可選。需要註意的是,如果是返回的對象的方法,返回的是方法的內存地址,如果需要運行這個方法,可以在後面添加一對括號。
        obj = cls.init(ret[‘name‘])   # 實例化 獲取實例對象進行以下對象方法的操作
        while True:
            for id,item in enumerate(cls.operate_lst,1):  #索引id以數字1開始計算
                print(id,item[0])
            func_str = cls.operate_lst[int(input(‘>>>‘)) - 1][1]
            print(func_str)
            if hasattr(obj,func_str):
                getattr(obj,func_str)()
else:
    print(‘登錄失敗‘)

  

面向對象之選課系統