目录

一、基础概念

  面向对象编程

    1、面向对象的几个核心特点

      1、class类

      2、object对象

      3、encapsulation封装

      4、inheritance继承

      5、polymorphism多态

    2、类变量与实例属性(实例变量)

    3、私有属性与私有方法

    4、析构函数

    5、继承

    6、多态

  二、作业:选课系统

一、基础概念

 1、面向对象编程

  OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

  1、面向对象的几个核心特性如下:

    1、Class 类
      一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法

    2、Object 对象 
      一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同

    3、Encapsulation 封装
      在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法

    4、Inheritance 继承
      一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承

    5、Polymorphism 多态
      多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
      多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定

  1、通过例子说明类的用法与类的封装:

  例子:创建一个角色扮演游戏,通过实例化引入不同角色

class Role(object):#新式类,所有的主类,都需要继承object类,object类是一个通类
n = 123
def __init__(self,name,role,weapon,life_vaule=100,money=15000):#life_value和money目前为默认参数,不需要实例化时传参
'''
构造函数:在实例化时做类的初始化工作,将实例化这些定义好的变量名
'''
self.name = name #如果为普通函数,局部变量在函数结束后会失去意义,但是类中构造函数会将实例化变量一直传递整个类中
self.role = role
self.weapon = weapon
'''
Role类通过该构造函数定义实例化变量名
''' def shot(self): #除了构造函数外,这些函数叫做类的方法
print('shotting....') def got_shot(self):
print('ah...,I got shot...') def buy_gun(self,gun_name):#在构造函数以外,也可以通过在函数内定义变量,只是这些变量需要调用时单独复制
print('%s just bought %s' %(self.name,gun_name)) print(Role) #在没有实例化之前,类就已经存在与内存中
#输出
<class '__main__.Role'> print(Role.n) #Role.n中的n叫做类变量,和类一样,类变量在实例化之前就存在于内存中,同时,实例化后类变量也仍然只存在于类所在内存中,不会复制到实例化的内存中
#输出
123 r1 = Role('alex','police','B21' ) #对Role类进行实例化,实例化过程是将通过构造函数将类中的变量复制为实例化变量,这时通过调用Role中的self,将实例化r1本身也赋值,得到实例化变量
#同时需要注意的是,类的方法,也就是类中的函数仍然保存在类中,不会被复制到实例化变量中,实例化在调用时,通过类方法中的self代表不同实例化的引用,避免类没法区分,这样做的优点为节省内存空间 r2 = Role('jack','terrist','AK47') #对该Role类进行另一个实例化引用 print(r1.name,r1.role,r1.weapon)
#输出alex police B21
print(r2.name,r2.role,r2.weapon)
#输出
jack terrist AK47

  2、类变量与实例属性(实例变量)

  类的变量查找顺序为当实例变量与类变量重名时,会复制一份实例化变量进行复制,这时的输出覆盖类变量结果,因为实例化变量在自己所在内存空间引入了一个新的实例化变量,而另外一个实例化不受此影响

class Role(object):
n = 123
def __init__(self,name,role,weapon,life_vaule=100,money=15000):
self.name = name
self.role = role
self.weapon = weapon def shot(self):
print('shotting....') def got_shot(self):
print('ah...,I got shot...') def buy_gun(self,gun_name):
print('%s just bought %s' %(self.name,gun_name)) print(Role.n)
#输出
123
r1 = Role('alex','police','B21' )
print(r1.n) #类变量属于共有的变量,不会因为实例化而改变
#输出
123
r1.n = 456 #类的变量查找顺序为当实例变量与类变量重名时,会复制一份实例化变量进行复制,这时的输出覆盖类变量结果,因为实例化变量在自己所在内存空间引入了一个新的实例化变量,而另外一个实例化不受此影响
print(r1.n)
#输出
456
r2 = Role('jack','terrist','AK47')
print(r2.n)
#输出
123

  

  类变量的用途:

  大家共用的属性,节省内存开销

class Person(object):

    cn = '中国'
def __init__(self,name,age,addr):
self.name = name
self.age = age
self.addr = addr p1 = Person('alex',22,'beijing')
print(p1.cn)
#输出
#中国
p2 = Person('jack',22,'shanghai')
print(p2.cn)
#输出
#中国

  当类变量为列表、字典时,可以通过实例化赋值,而将实例化的赋值引入类变量中

class Role(object):
n = 123
n_list = []
def __init__(self,name,role,weapon,life_vaule=100,money=15000):
self.name = name
self.role = role
self.weapon = weapon def shot(self):
print('shotting....') def got_shot(self):
print('ah...,I got shot...') def buy_gun(self,gun_name):
print('%s just bought %s' %(self.name,gun_name)) print(Role.n_list)
#输出
[]
r1 = Role('alex','police','B21' )
print(r1.n_list)
#输出
[]
r1.n_list.append(456) #当类变量为列表或字典时,会因为实例变量添加内容到源类变量中而导致引用改变,但是这也说明了类变量不会随着实例化而被引入到实例化变量中
print(r1.n_list)
#输出
[456]
r2 = Role('jack','terrist','AK47')
print(r2.n_list)
#输出
[456]

  实例化属性的重新增删改

class Role(object):
n = 123
n_list = []
def __init__(self,name,role,weapon,life_vaule=100,money=15000):
self.name = name
self.role = role
self.weapon = weapon def shot(self):
print('shotting....') def got_shot(self):
print('ah...,I got shot...') def buy_gun(self,gun_name):
print('%s just bought %s' %(self.name,gun_name)) r1 = Role('alex','police','B21' ) r1.sex = 'M' #增加实例化属性
print(r1.sex)
#输出M
r1.name = 'Tom' #修改实例化属性
print(r1.name) print(r1.role)
#输出
police
del r1.role
print(r1.role)
#输出
AttributeError: 'Role' object has no attribute 'role' r2 = Role('jack','terrist','AK47') #对应实例r1的任何操作对r2都没有任何印象
print(r2.sex)
#输出print(r2.sex)AttributeError: 'Role' object has no attribute 'sex'

  

  3、私有属性与私有方法

    a)私有属性(私有变量)

class Role(object):
n = 123
def __init__(self,name,role,weapon,life_vaule=100,money=15000):
self.name = name
self.role = role
self.weapon = weapon
self.__life_vaule = life_vaule #定义私有变量 def shot(self):
print('shotting....') def got_shot(self):
print('ah...,I got shot...') def buy_gun(self,gun_name):
print('%s just bought %s' %(self.name,gun_name)) r1 = Role('alex','police','B21' ) r2 = Role('jack','terrist','AK47')
print(r1.__life_value)
#输出
AttributeError: 'Role' object has no attribute '__life_value' #私有变量在实例化时没法调用

      对于私有属性,可以通过在类中定义类的方法的方式间接查看私有属性(私有变量)

class Role(object):
n = 123
def __init__(self,name,role,weapon,life_vaule=100,money=15000):
self.name = name
self.role = role
self.weapon = weapon
self.__life_vaule = life_vaule def shot(self):
print('shotting....') def got_shot(self):
print('ah...,I got shot...') def buy_gun(self,gun_name):
print('%s just bought %s' %(self.name,gun_name)) def show_status(self): #
print('%s has %s life value' %(self.name, self.__life_vaule)) #通过类的方法间接查看私有属性 r1 = Role('alex','police','B21' )
r1.show_status() #调用该类方法
#输出alex has 100 life value
r2 = Role('jack','terrist','AK47')

      b)私有方法

        同私有属性一样,前面加def  __show_status(self):  就将方法变为私有方法了

class Role(object):
n = 123
def __init__(self,name,role,weapon,life_vaule=100,money=15000):
self.name = name
self.role = role
self.weapon = weapon
self.__life_vaule = life_vaule def shot(self):
print('shotting....') def got_shot(self):
print('ah...,I got shot...') def buy_gun(self,gun_name):
print('%s just bought %s' %(self.name,gun_name)) def show_status(self):
print('%s has %s life value' %(self.name, self.__life_vaule)) #通过类的方法间接查看私有变量 def __show_status(self): #定义私有方法
print('aa') r1 = Role('alex','police','B21' )
r1.show_status() #调用该类方法
#输出
#alex has 100 life value
r2 = Role('jack','terrist','AK47')
r1.__show_status()

  4、析构函数

    不需要加任何变量,在实例化调用结束后,自动执行 ,目的完成实例化的收尾工作,例如断开数据库 关闭打开的文件等

class Role(object):
n = 123
def __init__(self,name,role,weapon,life_vaule=100,money=15000):
self.name = name
self.role = role
self.weapon = weapon
self.__life_vaule = life_vaule def shot(self):
print('shotting....') def got_shot(self):
print('ah...,I got shot...') def buy_gun(self,gun_name):
print('%s just bought %s' %(self.name,gun_name)) def show_status(self):
print('%s has %s life value' %(self.name, self.__life_vaule)) #通过类的方法间接查看私有变量 def __del__(self): #析构函数,不需要加任何变量,在实例化调用结束后,自动执行 ,目的完成实例化的收尾工作,例如断开数据库 关闭打开的文件等
print('%s is gone' % self.name) r1 = Role('alex','police','B21' )
r1.got_shot()
#输出
ah...,I got shot...
r2 = Role('jack','terrist','AK47')
r2.got_shot()
#输出
ah...,I got shot...
alex is gone #由于r1在实例化执行完所需任务后没有明确表示实例化引用结束,所以在r2也引用结束后,两者再先后自动执行析构函数
jack is gone

如果需要在r1结束后立即自动执行析构函数,需要使用del 方法

class Role(object):
n = 123
def __init__(self,name,role,weapon,life_vaule=100,money=15000):
self.name = name
self.role = role
self.weapon = weapon
self.__life_vaule = life_vaule def shot(self):
print('shotting....') def got_shot(self):
print('ah...,I got shot...') def buy_gun(self,gun_name):
print('%s just bought %s' %(self.name,gun_name)) def show_status(self):
print('%s has %s life value' %(self.name, self.__life_vaule)) #通过类的方法间接查看私有变量 def __del__(self): #析构函数,不需要加任何变量,在实例化调用结束后,自动执行 ,目的完成实例化的收尾工作,例如断开数据库 关闭打开的文件等
print('%s is gone' % self.name) r1 = Role('alex','police','B21' )
r1.got_shot()
#输出
ah...,I got shot...
del r1 #在r1执行完毕后立即删除该r1实例化的名字,表示 引用完毕,会立即自动执行析构函数
#输出
alex is gone
r2 = Role('jack','terrist','AK47')
r2.got_shot() #输出
ah...,I got shot...
jack is gone

 备注:

  python程序释放内存的条件,在python解释器在周期性扫描过程中,只有检测到变量名或者实例化的名称消失后才会释放内存,所以如果类与函数、变量如果名称仍然存在,会一直占据内存不会主动释放,除非通过del删除

   5、继承

    上述例子将类的概念与类的封装介绍了一下,下面继续介绍类的继承:

class People(object):  #主类,新式类
def __init__(self,name, age):
self.name = name
self.age = age def eat(self):
print('%s is eating' %self.name) def sleep(self):
print('%s is sleeping..' % self.name) def talk(self,obj):
print('%s is talking with %s' %(self.name,obj.name)) class Man(People): #继承People类
def __init__(self,name,age, money): #重构父类的构造函数,先将所有的属性写一遍
super(Man,self).__init__(name,age) #新式类的继承父类构造函数方法,这种方式更方便,引用父类的构造函数中的属性
self.money = money #构造属于自己类的属性
print('%s 一出生就有$%s 钱' %(self.name,self.money)) def piao(self):
print('%s is piao.......' % self.name) def sleep(self): #和父类中类方法相同
People.sleep(self) #可以将父类中方法引用
print('Man is sleeping' ) #引用完毕后执行自有的方法 class Woman(People): def get_birth(self):
print('%s is borin a baby' % self.name) m1 = Man('alex', 22, 10000)
#输出
alex 一出生就有$10000 钱
w1 = Woman('Suse',19)
m1.piao()
#输出
alex is piao.......
m1.eat()
#输出
alex is eating
m1.talk(w1)
#输出
alex is talking with Suse
m1.sleep()
#输出
alex is sleeping.. #先执行了People中sleep方法的内容
Man is sleeping
w1.get_birth()
#输出
Suse is borin a baby
'''
Man与Woman类继承People类,在Man中重构了构造函数,在继承了People类的属性后,重构了自己的特有属性,在调用方式时,Man和Woman类实例都可以直接调用People类的方法
'''

  继承可以多态继承,即一个子类可以继承多个父类,继承关系的构造函数引用按照广度继承方式进行

class People(object):  #主类,新式类
def __init__(self,name, age):
self.name = name
self.age = age
self.friends = [] #可以不用传,设置空列表,后面直接往该列表里写入内容
self.friends1 = [] def eat(self):
print('%s is eating' %self.name) def sleep(self):
print('%s is sleeping..' % self.name) def talk(self,obj):
print('%s is talking with %s' %(self.name,obj.name)) class Relation(object):
def make_friends(self,obj):
print('%s is making friend with %s' %(self.name, obj.name))
self.friends.append(obj) #直接写入obj,即实例化,在修改该实例化属性后,这里会跟着修改
self.friends1.append(obj.name) class Man(Relation,People): #继承People类
def __init__(self,name,age, money): #重构父类的构造函数,先将所有的属性写一遍
super(Man,self).__init__(name,age) #新式类的继承父类构造函数方法,这种方式更方便,引用父类的构造函数中的属性
self.money = money #构造属于自己类的属性
print('%s 一出生就有$%s 钱' %(self.name,self.money)) def piao(self):
print('%s is piao.......' % self.name) def sleep(self): #和父类中类方法相同
People.sleep(self) #可以将父类中方法引用
print('Man is sleeping' ) #引用完毕后执行自有的方法 class Woman(Relation,People): def get_birth(self):
print('%s is borin a baby' % self.name) m1 = Man('alex', 22, 10000)
w1 = Woman('Suse',19)
w2 = Woman('Jane',18)
m1.make_friends(w1)
#输出
alex is making friend with Suse m1.make_friends(w2)
#输出
alex is making friend with Jane for line in m1.friends:
print(line.name)
#输出
Suse
Jane w2.name = 'Rose' #当修改了w2的name后,在friends列表的变量会跟着修改
for line in m1.friends:
print(line.name)
#输出
Suse
Rose for line in m1.friends1:
print(line)
#输出
Suse
Rose w2.name = 'Rose'
for line in m1.friends1:
print(line)
#输出
Suse
Rose

  补充继承方式:

  1、深度继承:当子类继承多个父类时,子类如果没有定义构造函数会直接按照从下到上的方法继承父类构造函数,如果父类有构造函数就直接检查父类的构造函数,如果父类没有构造函数会先去查看父类函数是否有父类继承,如果有会直接查找父类的父类的构造函数,如果父类没有父类,会再去查看第二个父类是否有构造函数

  2、广度继承:当子类继承多个父类时,子类如果没有定义构造函数会直接按照从左到右的方法继承父类构造函数,如果父类有构造函数就直接检查父类的构造函数,如果父类没有构造函数会先去查看第二个父类是否有构造函数,如果第二个父类没有构造函数,会继续查看第一个父类的父类是否有构造函数

    python2中,经典类按照深度继承方法继承,新式类按照广度继承方法继承

    python3中,无论是经典类还是新式类都按照广度方法继承

例子说明:

class A(object):
def __init__(self):
print('A') class B(object):
def __init__(self):
print('B') class C(A):
pass
#def __init__(self):
# print('C') class D(B):
pass
#def __init__(self):
# print('D') class E(C,D):
pass
#def __init__(self):
# print('E') r1 = E()
#当CD本身都没有构造函数,会查找C父类是否有构造函数,C的父类A有构造函数,所以输出为
A
class A(object):
pass
#def __init__(self):
# print('A') class B(object):
def __init__(self):
print('B') class C(A):
pass
#def __init__(self):
# print('C') class D(B):
pass
#def __init__(self):
# print('D') class E(C,D):
pass
#def __init__(self):
# print('E') r1 = E()
#当CD本身都没有构造函数,会查找C父类是否有构造函数,C的父类A没有构造函数,所以输出为
B
class A(object):
pass
#def __init__(self):
# print('A') class B(object):
def __init__(self):
print('B') class C(A):
pass
#def __init__(self):
# print('C') class D(B):
pass
#def __init__(self):
# print('D') class E(C,D):
pass
#def __init__(self):
# print('E') r1 = E()
#当CD本身都没有构造函数,会查找C父类是否有构造函数,C的父类A没有构造函数,所以输出为
C
class A(object):
pass
#def __init__(self):
# print('A') class B(object):
def __init__(self):
print('B') class C(A):
pass
#def __init__(self):
# print('C') class D(B):
pass
#def __init__(self):
# print('D') class E(C,D):
pass
#def __init__(self):
# print('E') r1 = E()
#当CD本身都没有构造函数,会查找C父类是否有构造函数,C的父类A没有构造函数,所以输出为
B

  当子类有多个父类并且需要继承父类构造函数时,如果找到了一个父类构造函数就立即停下,不会继续查找其他父类是否也含有构造函数  

class People(object):  #主类,新式类
def __init__(self,name, age):
self.name = name
self.age = age
self.friends = [] #可以不用传,设置空列表,后面直接往该列表里写入内容
self.friends1 = [] def eat(self):
print('%s is eating' %self.name) def sleep(self):
print('%s is sleeping..' % self.name) def talk(self,obj):
print('%s is talking with %s' %(self.name,obj.name)) class Relation(object):
def __init__(self,name,age):
pass
def make_friends(self,obj):
print('%s is making friend with %s' %(self.name, obj.name))
self.friends.append(obj)
self.friends1.append(obj.name) class Woman(Relation,People): def get_birth(self):
print('%s is borin a baby' % self.name) w1 = Woman('Suse',19) #w1在Woman中按照广度继承方式继承Relation的构造函数,但是Relation中没有定义name和age的类属性,所以w1没法找到该属性
print(w1.name)

  6、多态

  多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
 
  Pyhon 很多语法都是支持多态的,比如 len(),sorted(), 你给len传字符串就返回字符串的长度,传列表就返回列表长度
class Animal(object):
def __init__(self,name):
self.name = name #@staticmethod
def animal(obj): #多态,在父类中实现只调用一种接口,多种表现,达到接口的重用
obj.eat() class Dog(Animal):
def talk(self):
print('%s:喵喵喵' %self.name)
def eat(self):
print('%s: eat bone!' %self.name) class Cat(Animal):
def talk(self):
print('%s: 汪汪汪' %self.name) def eat(self):
print('%s: eat fish!' %self.name) c1 = Dog('Alex')
d1 = Cat('Tom') Animal.animal(c1)
Animal.animal(d1)

  例子:

class School(object):
def __init__(self,name,addr):
self.name = name
self.addr = addr
self.students = []
self.staffs = [] def enroll(self,stu_obj):
print('为学员%s办理注册手续' %stu_obj.name)
self.students.append(stu_obj) def hire(self,staff_obj):
print('雇佣%s老师' %staff_obj.name)
self.staffs.append(staff_obj) class SchoolMember(object):
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex def tell(self):
print('''
Name: %s
Age: %s
Sex: %s
''' %(self.name,self.age,self.sex),end='') def tell_oneself(obj):
obj.tell() class Teacher(SchoolMember):
def __init__(self,name,age,sex,salary,course):
super(Teacher, self).__init__(name,age,sex)
self.salary = salary
self.course = course def tell(self):
print('info of teacher %s'.center(15,'+') % self.name,end='')
SchoolMember.tell(self)
print('''
Salary: %s
Course: %s
''' %(self.salary,self.course)) def teach(self):
print('%s is teaching %s' %(self.name,self.course)) class Students(SchoolMember):
def __init__(self,name,age,sex,stu_id,grade):
super(Students, self).__init__(name,age,sex)
self.stu_id = stu_id
self.grade = grade def tell(self):
print('info of student %s'.center(15,'+') % self.name,end='')
SchoolMember.tell(self)
print('''
Stu_id: %s
Grade: %s
''' %(self.stu_id,self.grade)) def pay_tuition(self,amount):
print('%s has paid tuition for %s' %(self.name,amount)) school = School('Oldboy','beijing') t1 = Teacher('oldboy',56,'XXY',200000, 'linux')
t2 = Teacher('alex', 22,'M', 3000, 'python')
s1 = Students('Chenronghua', 18,'M', 1001, 'python')
s2 = Students('Xuliangwei', 20,'M',1002, 'linux') teacher1 = SchoolMember.tell_oneself(t1)
#输出
info of teacher oldboy
Name: oldboy
Age: 56
Sex: XXY Salary: 200000
Course: linux teacher2 = SchoolMember.tell_oneself(t2)
#输出
info of teacher alex
Name: alex
Age: 22
Sex: M Salary: 3000
Course: python student1 = SchoolMember.tell_oneself(s1)
#输出
info of student Chenronghua
Name: Chenronghua
Age: 18
Sex: M Stu_id: 1001
Grade: python student2 = SchoolMember.tell_oneself(s2)
#输出
info of student Xuliangwei
Name: Xuliangwei
Age: 20
Sex: M Stu_id: 1002
Grade: linux school.hire(t1)
#输出
雇佣oldboy老师 school.hire(t2)
#输出
雇佣alex老师 school.enroll(s1)
#输出
为学员Chenronghua办理注册手续 school.enroll(s2)
#输出
为学员Xuliangwei办理注册手续 for line in school.staffs:
print(line.name)
#输出
oldboy
alex for line in school.students:
line.pay_tuition(5000) #输出
Chenronghua has paid tuition for 5000
Xuliangwei has paid tuition for 5000

二、作业:选课系统

角色:学校、学员、课程、讲师
要求:
1. 创建北京、上海 2 所学校
2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开
3. 课程包含,周期,价格,通过学校创建课程 
4. 通过学校创建班级, 班级关联课程、讲师
5. 创建学员时,选择学校,关联班级
5. 创建讲师角色时要关联学校, 
6. 提供两个角色接口
6.1 学员视图, 可以注册, 交学费, 选择班级,
6.2 讲师视图, 讲师可管理自己的班级, 上课时选择班级, 查看班级学员列表 , 修改所管理的学员的成绩 
6.3 管理视图,创建讲师, 创建班级,创建课程

7. 上面的操作产生的数据都通过pickle序列化保存到文件里

程序结构:

1、bin模块下选课系统.py

import os
import sys BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0,BASE_DIR) from core import main
#from config import settings if __name__ == '__main__':
obj = main.Manage_center() #对main函数实例化
obj.run()#运行main函数

2、config下settings.py

import os
import sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) db_path = os.path.join(BASE_DIR,'database/') school_db_file = os.path.join(db_path,'school')

3、core中main.py

import os
import sys
import shelve BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,BASE_DIR) from config import settings
from modules.School import School class Manage_school(object):
def __init__(self):
if os.path.exists(settings.school_db_file+'.db'):
self.school_db = shelve.open(settings.school_db_file)
self.run_manage()
self.school_db.close()
else:
print('\033[31;1m系统信息: 初始化数据库\033[0m')
self.initialize_school()
self.run_manage()
self.school_db.close() def initialize_school(self):
self.school_db = shelve.open(settings.school_db_file)
self.school_db['北京'] = School('北京','中国北京')
self.school_db['上海'] = School('上海','中国上海')
#print(self.school_db) def run_manage(self):
quit_list = ['q', 'quit', 'QUIT', 'Q'] #输入该列表中的值,返回到上一级目录
while True:
for key in self.school_db:
print('学校名称:', key)
choice_school = input('\033[32;1m输入你想选择管理的学校,按q|QUIT退出: ').strip()
if choice_school in self.school_db:
self.choice_school = choice_school
self.school_obj = self.school_db[choice_school]
while True:
print('''\033[32;1m
欢迎来到老男孩%s校区:
1. 添加课程
2. 增加班级
3. 添加讲师
4. 查看课程
5. 查看班级
6. 查看讲师
7. 退出程序
8. 重选校区
\033[0m''' % self.school_obj.school_name)
user_choice = input('\033[33;1m请选择对应的数字: \033[0m').strip()
choice_dict = {
'': 'add_course',
'': 'add_class',
'': 'add_teacher',
'': 'check_course',
'': 'check_class',
'': 'check_teacher',
'': 'exit_school',
'': 'exit_choice'
}
if user_choice in choice_dict:
if choice_dict[user_choice] == 'add_class':
class_print = getattr(self,choice_dict[user_choice])()
print(class_print[0])
elif choice_dict[user_choice] == 'exit_choice':
getattr(self,choice_dict[user_choice])()
break
else:
getattr(self,choice_dict[user_choice])()
else:
print('\033[31;1m选择错误,请重新选择!\033[0m')
elif choice_school in quit_list:
break
else:
print('\033[31;1m没有这个学校,请重新选择\033[0m') def add_course(self):
'''增加课程'''
course_name = input('''\033[34;0m输入要添加课程的名称:\033[0m''').strip()
if course_name in self.school_obj.school_course:
print('\033[32;1m课程存在\033[0m')
self.school_obj.show_course(course_name)
course_update = input('\033[31;1m是否需要更新课程价格或周期?(YES|NO) \033[0m').strip()
if course_update == 'YES' or course_update == 'Y' or course_update == 'yes':
course_price = input('''\033[34;0m输入要添加课程的价格:\033[0m''').strip()
course_outline = input('''\033[34;0m输入要添加课程的时长:\033[0m''').strip()
self.school_obj.create_course(course_name,course_price,course_outline)
print('\003[34;1m课程%s更新完成\033[0m' % self.school_obj.school_course[course_name].course_name )
self.school_db.update({self.choice_school: self.school_obj})
elif course_update == 'NO' or course_update == 'N' or course_update == 'no':
pass
else:
print('\033[31;1m错误输入!\033[0m')
else:
course_price = input('''\033[34;0m输入要添加课程的价格:\033[0m''').strip()
course_outline = input('''\033[34;0m输入要添加课程的时长:\033[0m''').strip()
self.school_obj.create_course(course_name,course_price,course_outline)
print("\33[32;1m课程添加成功\33[0m")
self.school_db.update({self.choice_school: self.school_obj}) def add_class(self):
course_name = input('\033[33;1m输入你要创建的课程名: \033[0m').strip()
class_name = input('\033[33;1m输入课程对应的班级名: \033[0m').strip() if class_name not in self.school_obj.school_class:
if course_name in self.school_obj.school_course:
course_obj = self.school_obj.school_course[course_name]
self.school_obj.create_class(class_name,course_obj)
self.school_db.update({self.choice_school: self.school_obj})
return ['\033[32;1m课程对应的班级创建完毕\033[0m' ,2]
else:
return ['\033[31;1m关联的课程不存在\033[0m', 1]
else:
self.school_db.update({self.choice_school: self.school_obj})
return ['\033[31;1m该班级已存在!\033[0m', class_name] def add_teacher(self):
teacher_name = input('\033[32;1m请输出创建讲师的姓名: \033[0m').strip()
if teacher_name in self.school_obj.school_teacher:
self.school_obj.show_teacher(teacher_name)
teacher_chage_class = input('\033[31;1m是否需要重新更换讲师班级?(YES|NO) \033[0m').strip()
if teacher_chage_class == 'YES' or teacher_chage_class == 'Y' or teacher_chage_class == 'yes':
#class_name = input('\033[33;1m输入需要调整到的班级名: \033[0m').strip()
self.class_choose(teacher_name)
elif teacher_chage_class == 'NO' or teacher_chage_class == 'N' or teacher_chage_class == 'no':
print('\033[34;1m不修改班级信息!\033[0m')
else:
print('\033[31;1m错误输入!\033[0m')
else:
self.class_choose(teacher_name) def class_choose(self,teacher_name):
class_choice = self.add_class()
if class_choice[1] == 1 or class_choice[1] == 2:
print('\033[31;1m班级不存在!\033[0m')
else:
#class_obj = self.school_obj.school_class[class_choice[1]]
#self.school_obj.create_teacher(teacher_name,class_choice[1],class_obj)
self.school_obj.create_teacher(teacher_name,class_choice[1])
print('\033[32;1m讲师添加完毕!\033[0m')
self.school_db.update({self.choice_school: self.school_obj}) def check_course(self):
self.school_obj.show_course() def check_class(self):
self.school_obj.show_class() def check_teacher(self):
self.school_obj.show_teacher() def exit_school(self):
exit('\033[31;1m退出程序!\033[0m') def exit_choice(self):
print('\033[31;1m重新选择校区!\033[0m') class Manage_student(object): def __init__(self):
if os.path.exists(settings.school_db_file+'.db'):
self.school_db = shelve.open(settings.school_db_file)
self.run_manage()
self.school_db.close()
else:
exit('\033[31;1m学校不存在!\033[0m') def run_manage(self):
print('环境进入学员视图')
for key in self.school_db:
print('学校名称:' ,key)
choice_school = input('\33[34;0m输入选择注册的学校名:\33[0m').strip()
self.choice_school = choice_school
if choice_school in self.school_db:
self.school_obj = self.school_db[choice_school]
student_name = input('\033[34;0m输入学生的姓名:\033[0m').strip()
while True:
if student_name in self.school_obj.school_student:
print('\033[32;1m该学员已注册\033[0m')
print('\033[32;1m学员已参加的班级:\033[0m')
self.school_obj.show_student(student_name)
student_age = self.school_obj.school_student[student_name].student_age
print('可以选择的班级如下'.center(15,'#'))
self.school_obj.show_class_course()
class_choice = input('''\033[34;0m是否需要增加新的班级或退出该界面(Q|q):\033[0m''').strip()
if class_choice not in self.school_obj.school_student[student_name].student_class and class_choice in self.school_obj.school_class:
self.school_obj.create_student(student_name,student_age,class_choice)
print('\033[32;1m学员更新完毕\033[0m')
self.school_db.update({self.choice_school: self.school_obj})
elif class_choice == 'Q' or class_choice == 'q':
break
elif class_choice in self.school_obj.school_student[student_name].student_class:
print('\033[31;1m该课程已被选择,请重新输入!\033[0m')
else:
print('\033[31;1m没有该课程\033[0m')
else:
student_age = input('\033[34;0m需要注册信息,输入学生的年龄:\033[0m').strip()
if student_age.isalnum() and 5 < student_age < 100:
print('可以选择的班级如下'.center(15,'#'))
self.school_obj.show_class_course()
class_choice = input('''\033[34;0m是否需要增加新的班级或退出该界面(Q|q):\033[0m''').strip()
if class_choice in self.school_obj.school_class:
self.school_obj.create_student(student_name,student_age,class_choice)
print('\033[32;1m学员更新完毕\033[0m')
self.school_db.update({self.choice_school: self.school_obj})
elif class_choice == 'Q' or class_choice == 'q':
break
else:
print('\033[31;1m没有该课程\033[0m')
else:
print('\033[31;1m输入有误,请数字[5,99]之间的数字')
else:
print('\033[31;1m该学校不存在!\033[0m') class Manage_teacher(object): def __init__(self):
if os.path.exists(settings.school_db_file + ".db"): # shelve会生成三个文件,其中有.dat结尾
self.school_db = shelve.open(settings.school_db_file) # 打开学校数据库文件
self.run_manage() # 运行管理视图
self.school_db.close() # 关闭数据库文件
else:
exit("\033[31;1m数据库文件不存在,请先创建学校\033[0m") def run_manage(self):
for key in self.school_db:
print("学校名称:", key)
choice_school = input("\33[34;0m输入选择学校名:\33[0m").strip()
if choice_school in self.school_db:
self.choice_school = choice_school
self.school_obj = self.school_db[choice_school]
teacher_name = input('''\033[34;0m输入登录讲师的姓名:\033[0m''').strip()
while True:
if teacher_name in self.school_obj.school_teacher:
print('''
欢迎来到教师中心\n
1. 查看班级
2. 退出程序
3. 返回上一级目录
''')
teacher_dict = {
'': 'check_class',
'': 'exit_school',
'': 'exit_choice'
}
use_choice = input('\033[34;1m输入要操作的命令:\033[0m').strip()
if use_choice in teacher_dict:
if use_choice == '':
getattr(self,teacher_dict[use_choice])()
break
elif use_choice == '':
getattr(self,teacher_dict[use_choice])()
else:
getattr(self,teacher_dict[use_choice])(teacher_name)
else:
print('\033[31;1m输入错误,请重新输入\033[0m')
else:
print("\033[31;1m讲师不存在\033[0m")
break def check_class(self,teacher_name):
self.school_obj.show_teacher_classinfo(teacher_name) def exit_school(self):
exit('\033[31;1m退出程序!\033[0m') def exit_choice(self):
print('\033[31;1m退回到上一级目录\033[0m') def exit_flag():
exit('\033[31;1m退出程序\033[0m') controller_dict = {
'': Manage_school,
'': Manage_student,
'': Manage_teacher,
'': exit_flag
} class Manage_center(object):
def __init__(self):
pass def run(self):
exit_flag = False
while not exit_flag:
print('''\033[32;1m\n欢迎进入选课系统\n
1. 管理中心\n
2. 学生中心\n
3. 讲师中心\n
4. 退出系统\n
\033[0m''')
user_choice = input('\033[34;1m请输入您的选择\033[0m').strip()
if user_choice in controller_dict:
controller_dict[user_choice]() else:
print('\033[31;1m你的选择不存在,请重新选择\033[0m')

4、modules中

  Class.py

class Class(object):
def __init__(self,class_name,course_obj):
self.class_name = class_name
self.class_course = course_obj
self.class_student = {}

  Course.py

class Course(object):
def __init__(self,course_name,course_price,course_outline):
self.course_name = course_name
self.course_price = course_price
self.course_outline = course_outline

  School.py

import os
import sys
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,BASEDIR) from modules.Class import Class
from modules.Student import Student
from modules.Teacher import Teacher
from modules.Course import Course class School(object):
'''定义学校类,包括名称/地址/课程/班级/老师'''
def __init__(self,school_name,school_addr):
self.school_name = school_name
self.school_addr = school_addr
self.school_teacher = {}
self.school_teacher_class = {} #讲师对应的课程
self.school_course = {}
self.school_class = {}
self.school_student = {}
self.school_student_class = {} #学生对应的课程,由于shelve模块在main中只保存school函数中的条目,所以需要讲师与学员对应的课程都保留在这里 def create_course(self,course_name,course_price,course_outline):
'''创建课程'''
course_obj = Course(course_name,course_price,course_outline)
self.school_course[course_name] = course_obj def show_course(self,course_name=None):
'''查看课程'''
if course_name == None: #没有指定课程时可以查看所有课程
for key in self.school_course:
course_obj = self.school_course[key]
print(
'''
\033[32;1m
课程: %s
价格: %s
周期: %s \033[0m''' %(course_obj.course_name,course_obj.course_price,course_obj.course_outline)
)
elif course_name == course_name: #指定课程时查看
course_obj = self.school_course[course_name]
print(
'''
\033[32;1m
课程: %s
价格: %s
周期: %s \033[0m''' %(course_obj.course_name,course_obj.course_price,course_obj.course_outline)
) def create_class(self,class_name,course_obj): '''创建班级''' class_obj = Class(class_name,course_obj)
self.school_class[class_name] = class_obj def show_class(self):
'''查看班级'''
for key in self.school_class:
class_obj = self.school_class[key]
print(
'''
\033[32;1m
班级: %s
管理课程: %s
\033[0m''' %(class_obj.class_name,class_obj.class_course.course_name)
) def show_class_course(self):
for key in self.school_class:
class_obj = self.school_class[key]
course_obj = class_obj.class_course
print(
'''
\033[32;1m
班级: %s
关联课程 %s
价格: %s
周期: %s \033[0m''' %(class_obj.class_name,course_obj.course_name,course_obj.course_price,course_obj.course_outline)
) def create_teacher(self,teacher_name,class_name):
'''创建讲师'''
teacher_obj = Teacher(teacher_name)
class_obj = self.school_class[class_name]
if teacher_name not in self.school_teacher_class: #讲师对应的课程使用嵌套字典,初始化需要该方法填写内容
self.school_teacher_class[teacher_name] = {class_name: class_obj}
else:
teacher_teacher_class = self.school_teacher_class[teacher_name]#当字典中有讲师名称后,要添加而不是修改讲师对应班级,需要使用该方式添加
teacher_teacher_class[class_name] = class_obj
self.school_teacher[teacher_name] = teacher_obj
print(self.school_teacher_class) def show_teacher(self,teacher_name=None):
if teacher_name == None:
for key in self.school_teacher:
teacher_obj = self.school_teacher[key]
teacher_list = []
for line in self.school_teacher_class[key]: #调用该方式打印出讲师对应的班级
teacher_list.append(line)
print(
'''
\033[32;1m
讲师: %s
班级: %s
\033[0m''' %(teacher_obj.teacher_name,teacher_list)
)
elif teacher_name == teacher_name:
teacher_obj = self.school_teacher[teacher_name]
teacher_list = []
for line in self.school_teacher_class[teacher_name]: #调用该方式打印出讲师对应的班级
teacher_list.append(line)
print(
'''
\033[32;1m
讲师: %s
班级: %s
\033[0m''' %(teacher_obj.teacher_name,teacher_list)
) def create_student(self,student_name,student_age,class_name):
student_obj = Student(student_name,student_age)
self.school_student[student_name] = student_obj
class_obj = self.school_class[class_name]
if student_name not in self.school_student_class: #与讲师嵌套字典添加方式一致,初始使用该方法添加,如果存在在下面方法中添加而不是覆盖
self.school_student_class[student_name] = {class_name: class_obj}
else:
student_class = self.school_student_class[student_name]
student_class[class_name] = class_obj
class_obj.class_student[student_name] = student_obj def show_student(self,student_name = None):
if student_name == None:
for key in self.school_student:
student_obj = self.school_student[key]
student_class_list = []
for class_name in self.school_student_class[key]:
student_class_list.append(class_name)
print(
'''
\033[32;1m
学生: %s
年龄: %s
班级: %s
\033[0m''' % (student_obj.student_name,student_obj.student_age,student_class_list)
)
elif student_name == student_name:
student_obj = self.school_student[student_name]
student_class_list = []
for class_name in self.school_student_class[student_name]:
student_class_list.append(class_name)
print(
'''
\033[32;1m
学生: %s
年龄: %s
班级: %s
\033[0m''' % (student_obj.student_name,student_obj.student_age,student_class_list)
) def show_teacher_classinfo(self,teacher_name):
teacher_obj = self.school_teacher[teacher_name]
for key in teacher_obj.teacher_class:
class_obj = self.school_class[key] #通过该方法打印讲师对应的课程与学员列表
student_list = []
for line in class_obj.class_student: #通过该方法打印讲师对应的课程与学员列表
student_list.append(line)
print('''
\033[32;1m
班级: %s
关联课程: %s
学员: %s
\033[0m''' %(class_obj.class_name,class_obj.class_course.course_name,student_list))

  Student.py

class Student(object):
def __init__(self,student_name,student_age):
self.student_name = student_name
self.student_age = student_age

  Teacher.py

class Teacher(object):
def __init__(self,teacher_name):
self.teacher_name = teacher_name

5、db目录文件自动生成

  

Python学习笔记第六周的更多相关文章

  1. python学习笔记(六)文件夹遍历,异常处理

    python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ...

  2. Python学习笔记(六)

    Python学习笔记(六) Ubuntu重置root密码 Ubuntu 16.4 目录结构 Ubuntu 命令讲解 1. Ubuntu重置root密码 启动系统,显示GRUB选择菜单(如果默认系统启动 ...

  3. python学习笔记(六)——程序调试

    在我们平时编写程序时,常常会遇到各种错误,俗称BUG.而我们程序猿的工作常常需要对程序进行调试,也就是所谓的debug. 程序调试是将编制的程序投入实际运行前,用手工或编译程序等方法进行测试,修正语法 ...

  4. [Python学习笔记][第六章Python面向对象程序设计]

    1月29日学习内容 Python面向对象程序设计 类的定义与使用 类定义语法 使用class关键词 class Car: def infor(self): print("This is ca ...

  5. Python学习笔记第二十三周(Flask架构)

    目录: 一.变量引用 内容: 备注:PyCharm小技巧,comm+alt+l  自动修改格式,comm+alt+return  向上添加新行 一.变量引用 1.url生成 from flask im ...

  6. Python学习笔记第五周

    目录 一.基础概念 1.模块定义 2.包的定义 3.导入包的本质 4.导入模块的本质 5.导入方法 6.import的本质 7.导入优化 8.模块分类 9.标准库介绍 1.time与datetime ...

  7. python学习笔记(六)— 模块

    一.os.sys模块 import os print(os.getcwd())#取当前工作目录,绝对路径 print(os.chdir("../"))#更改当前目录 print(o ...

  8. python学习笔记(六)time、datetime、hashlib模块

    一.hashlib模块 python中的hashlib模块用来进行hash或者md5加密,而且这种加密是不可逆的,所以这种算法又被称为摘要算法.在python3的版本里,代替了md5和sha模块,主要 ...

  9. python 学习笔记十六 django深入学习一 路由系统,模板,admin,数据库操作

    django 请求流程图 django 路由系统 在django中我们可以通过定义urls,让不同的url路由到不同的处理函数 from . import views urlpatterns = [ ...

随机推荐

  1. 2017-4-18/缓存、CDN

    1. 什么是缓存,为什么要用缓存? 缓存就是数据交换的缓冲区(称作Cache),是存贮数据(使用频繁的数据)的临时地方.当用户查询数据,首先在缓存中寻找,如果找到了则直接执行.如果找不到,则去数据库中 ...

  2. HDFS - Shell命令

    HDFS - Shell命令 最近学习比较忙,本来想做一个搭建集群笔记,今天先记录HDFS-shell命令,明天,最迟明天下午我一定会做一个搭建集群的笔记.. 介绍一个我的集群搭建:一主三从 3个虚拟 ...

  3. 【转】Vue-详解设置路由导航的两种方法: <router-link :to="..."> 和router.push(...)

    一.<router-link :to="..."> to里的值可以是一个字符串路径,或者一个描述地址的对象.例如: // 字符串 <router-link to= ...

  4. get url img

    selenium     1● 了解selenium 这个是做 web页面测试,模拟用户测试   =====> pip install selenium 安装     2● django 用于接 ...

  5. do_bootrk

    1. LMB (logical memory blocks) lmb为uboot下的一种内存管理机制,用于管理镜像的内存.lmb所记录的内存信息最终会传递给kernel.在/include/lmb.h ...

  6. UVa 10795 - A Different Task 对称, 中间状态, 数位DP 难度: 3

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  7. unity3D开发的程序发布到Android平台上进行运行测试的详细步骤

    第一步    下载安装JDK 和SDK 1.需要配置java环境.点击链接进入ava的配置的方法:http://www.cnblogs.com/Study088/p/7496158.html 2.下载 ...

  8. day26-python操作redis二

    字符串的操作 #redis中的string 在内存中都是按照一个key对应一个valus来存储的 import redis pool = redis.ConnectionPool(host=" ...

  9. java③

    1.变量是什么? 变量====>一个数据在内存中 存储空间的表示! 在程序运行期间可以发生变化! *变量名 可以 迅速的从内存中 查询出 指定的变量! 2.数据类型: 数据类型 一共分为两种: ...

  10. day11 第一类对象 闭包 迭代器

    今日主要内容: 1 . 第一类对象 -->函数名--> 变量名 2. 闭包 -->函数的嵌套 3. 迭代器 --> 固定的思想 for 循环 第一类对象  : 函数对象介意向变 ...