python-33 面向对象之二:组合、继承

 

1.当类之间有显著的不同,并且较小的类是较大的类所需要的组件时,用组合较好

 

'''
1.组合:在一个类中以另外一个类的对象作为数据属性,称为类的组合
'''
class School:
    def __init__(self,name,add):
        self.name=name
        self.add=add

class Course:
    def __init__(self,name,price,priod,school):
        self.name=name
        self.price=price
        self.priod=priod
        self.school=school  #传入一个类,这样就构成了一个组合,一类中包含了另一个类

s1=School('清华','北京')
s2=School('科大','合肥')

c1=Course('python','1w','3mon',s1) #这就是组合,大类中包含小类
c2=Course('linux','2w','4mon',s2)

print(c1.school.name)
print(s1,'\n',c1.__dict__['school'])#打印 s1内存地址,地址相同
View Code

 

 2.当类之间有许多共同的功能,提取这些共同的功能做基类,用继承较好

    继承:具有两方面含义,一是继承父类的特性,二是具有自己衍生的特性

   单继承:从上往下继承,先继承祖先类,再继承子孙类的类数据属性和方法属性,实例化时,先查找自己的__init__方法,没有再往上找,直到找到为止,

                   如果都没有显示的__init__方法,调用object类的__init__方法

 

class A:
    print('---A---')
    def __init__(self,name):
        self.name=name
        print('A:name=%s'%self.name)
    def eat(self):
        print('%s正在吃ing'%self.name)
class B(A):
    a=1
    print('---B---')
class C(B):
    print('---C---')
    def __init__(self,sex,age):
        self.g=super().__init__('小a')
        self.sex=sex
        self.age=age
        print('C:sex=%s  age=%s'%(sex,age))

c=C('boy',50)#先打印 B C类的数据属性,相当于先将打印的代码加载到C类中,再调用父类的__init__,最后是自身的__init__方法
c.eat()#小a正在吃ing
print(c.__dict__)#{'name': '小a', 'g': None, 'sex': 'boy', 'age': 50},拥有了name数据属性
View Code

 

 

多继承:根据mro线性顺序表继承(广度优先查找),同样先继承所有父类的数据属性,再查找__init__,调用了哪个父类的__init__方法,就继承了该父类的所有其它方法属性,未被调用的父类,则不继承该父类的方法属性。

'''
1.组合:在一个类中以另外一个类的对象作为数据属性,称为类的组合
'''
class School:
    def __init__(self,name,add):
        self.name=name
        self.add=add

class Course:
    def __init__(self,name,price,priod,school):
        self.name=name
        self.price=price
        self.priod=priod
        self.school=school  #传入一个类,这样就构成了一个组合,一类中包含了另一个类

s1=School('清华','北京')
s2=School('科大','合肥')

c1=Course('python','1w','3mon',s1) #这就是组合,大类中包含小类
c2=Course('linux','2w','4mon',s2)

print(c1.school.name)
print(s1,'\n',c1.__dict__['school'])#打印 s1内存地址,地址相同

'''
 2. 继承:新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
     python中类的继承分为:单继承和多继承
'''
class Father:
    money=100   #继承类的属性和方法
    def __init__(self,name):
        self.name=name
        print('这是爸爸【name=%s】类'%self.name)
    def Habit(self):
        print('爸爸【name=%s】的坏习性:爱抽烟'%self.name)
    def work(self):
        print('Father教学生')
class Mother:
    car='路虎'
    def __init__(self,age,national ):
        self.age=age
        self.national=national
        print('这是妈妈【age=%d】类'%self.age)
    def Hobby(self):
        print('妈妈【age=%d】的爱好是打球'%self.age)

class Son(Father,Mother): #可以多继承,但实例化时,若自身没有__init__,则调用第一个父类的__init__,即Father.__init__
    def work(self):
       print('Son开汽车')


print(Father.__dict__)
print(Mother.__dict__)
print(Son.__dict__) #不包含父母类的任何属性{'__module__': '__main__', 'work': <function Son.work at 0x000000000225A0D0>, '__doc__': None}

f=Father('大明')#创建Father对象,调用__init__实例化一个f对象,返回:这是爸爸【name=大明】类
m=Mother(30,'美国人')# 这是妈妈【age=30】类

print(Son.__base__)#__base__只查看从左到右继承的第一个父类,<class '__main__.Father'>
print(Son.__bases__)#__bases__,查看所有父类,(<class '__main__.Father'>, <class '__main__.Mother'>)

s=Son('小明')#先调用自己的__init__,没有则调用继承的第一个父类,Father.__init__实例化一个s对象,故返回:这是爸爸【name=小明】类,

print(s.name,s.car,s.money)#能调用父母类的静态数据属性,小明 路虎 100
s.Habit()#能调用父类的方法属性,爸爸【name=小明】的坏习性:爱抽烟
s.work()#Son开汽车---->方法名相同,并不会改写父类的方法,
f.work()#Father教学生---->父类方法不变

s.Hobby()#出错,AttributeError: 'Son' object has no attribute 'age',因为实例化时调用的是第一个父类Father.__init_
View Code

 

class Grandpa:
    language='英语'
    def tell(self):
        print('Grandpa会讲%s'%self.language)

class Son1(Grandpa,Mother):
    def job(self):
        print('Son1 is a driver')
s1=Son1(15,'中国')
s1.Hobby()#这是妈妈【age=15】类,妈妈【age=15】的爱好是打球,Grandpa类没有.__init__,就调用Mother.__init__
print(Son1.mro())#继承顺序:[<class '__main__.Son1'>, <class '__main__.Grandpa'>, <class '__main__.Mother'>, <class 'object'>]
View Code

 总结:类中的方法属性都是与具体对象绑定的,而数据属性无具体对象绑定,所以,在多继承中,只有实例化了父类,即调用了父类的__init__方法后,才能调用该父类的其它方法属性,而没  有被实例化的父类,则不会继承其方法属性,但具有其数据属性。至于@staticmethod的类工具包,既不绑定类又不绑定对象的方法属性,是能继承的。@classmethod,类方法,也是被类继承。

posted @ 2019-01-16 22:56  优雅的代码  阅读(159)  评论(0编辑  收藏  举报