目录

 

一、基础概念

 

  面向对象编程

 

    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 = {
                         '1': 'add_course',
                         '2': 'add_class',
                         '3': 'add_teacher',
                         '4': 'check_course',
                         '5': 'check_class',
                         '6': 'check_teacher',
                         '7': 'exit_school',
                         '8': '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 = {
                        '1': 'check_class',
                        '2': 'exit_school',
                        '3': 'exit_choice'
                    }
                    use_choice = input('\033[34;1m输入要操作的命令:\033[0m').strip()
                    if use_choice in teacher_dict:
                        if use_choice == '3':
                            getattr(self,teacher_dict[use_choice])()
                            break
                        elif use_choice == '2':
                            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 = {
    '1': Manage_school,
    '2': Manage_student,
    '3': Manage_teacher,
    '4': 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目录文件自动生成

  

posted on 2017-02-26 16:50  爱python的小皮  阅读(438)  评论(0编辑  收藏  举报