第二十四天继承:
1.面向对象有三种方法:继承、多态、封装
2继承的定义:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A:#这个类成为父类,基类或者是超类 pass class B(A): #这种定义类的方式就是继承名字叫做子类、派生类 pass
3.一个父类可以被多次继承,一个子类也可以有多个父类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A:#这个类成为父类,基类或者是超类 pass class C: pass class B(A): #这种定义类的方式就是继承名字叫做子类、派生类 pass class D(C,A):#这个程序a被继承两次,而且一个子类继承了ca两个父类 pass
继承的关系图如下:
4.怎么再程序中查看继承关系:使用__base__:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A:#这个类成为父类,基类或者是超类 pass class C: pass class B(A): #这种定义类的方式就是继承名字叫做子类、派生类 pass class D(C,A):#这个程序a被继承两次,而且一个子类继承了ca两个父类 pass print(A.__bases__)#没有继承父类的默认继承object print(D.__bases__) #有继承的会打印出继承的父类名称 结果为 (<class 'object'>,) (<class '__main__.C'>, <class '__main__.A'>)
5.继承和抽象:
抽象即抽取类或者比较像的东西
抽象分成两个层次:
1.将奥巴马和梅西这两个对象比较成像的部分抽取成类
2.将人、猪、狗这三个比较像的部分抽成父类。
抽象最主要的作用就是划分类别:
6.使用继承的作用就是将每一个类中重复的代码用一个新的类进行写:(以人狗大战为例:)属性:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Animial: def __init__(self,*args): self.name=args[0] self.blood=args[1] self.aggr=args[2] self.sex=args[3] class Dog(Animial): pass class Person(Animial): pass jin=Dog('进老爸',100,3,'不详') ret1=jin.aggr print(ret1)
7.使用继承 来继承父类中的方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Animial: def __init__(self,*args): self.name=args[0] self.blood=args[1] self.aggr=args[2] self.sex=args[3] self.func() class Dog(Animial): def func(self): print(self.blood) class Person(Animial): def func(self): print(self.blood) jin=Dog('进老爸',100,3,'不详')#hui'sheng'cheng'yi 结果为 100
8.如果既需要子类中的个性有需要有自己的个性:
方法一:使用父类名字.__init__(self,需要调用父类的属性)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Animial: def __init__(self,name,aggr,blood): self.name=name self.blood=blood self.aggr=aggr class Dog(Animial): def __init__(self,name,aggr,blood,kind): #这种发放可以读取到所有子类的属性 Animial.__init__(self,name,aggr,blood)#把父类中共有的属性加到子类使用 self.kind=kind #子类中独有的属性 class Person(Animial): def __init__(self,name,aggr,blood,sex): Animial.__init__(self,name,aggr,blood) self.sex=sex jin=Dog('进老爸',100,3,'不详') alex=Person('alex',100,6,None) print(jin.name) print(jin.kind) print(alex.sex) 结果为 进老爸 不详 None
第二种方法:使用super,这种方法不需要加self,其他类型的量还是需要的 第二种方法必须在python3以上的版本中使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Animial: def __init__(self,name,aggr,blood): self.name=name self.blood=blood self.aggr=aggr class Dog(Animial): def __init__(self,name,aggr,blood,kind): #这种发放可以读取到所有子类的属性 super().__init__(name,aggr,blood)#把父类中共有的属性加到子类使用 self.kind=kind #子类中独有的属性 class Person(Animial): def __init__(self,name,aggr,blood,sex): Animial.__init__(self,name,aggr,blood) self.sex=sex jin=Dog('进老爸',100,3,'不详') alex=Person('alex',100,6,None) print(jin.name) print(jin.kind) print(alex.sex) 结果为 进老爸 不详 None
9.同样调用父类方法的时候同时也想使用子类里面同样名字的函数方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Animial: def __init__(self,name,aggr,blood): self.name=name self.blood=blood self.aggr=aggr def eat(self): print('吃回血药') self.blood+=100 class Dog(Animial): def __init__(self,name,aggr,blood,kind): #这种发放可以读取到所有子类的属性 super().__init__(name,aggr,blood)#把父类中共有的属性加到子类使用 self.kind=kind #子类中独有的属性 class Person(Animial): def __init__(self,name,aggr,blood,sex): Animial.__init__(self,name,aggr,blood) self.sex=sex def eat(self): #如果只是这样写永远不会调用父类里的eat方法 print('在人的类中吃加血药') self.blood+=50 jin=Dog('进老爸',100,3,'不详') alex=Person('alex',100,6,None) print(jin.name) print(jin.kind) print(alex.sex) alex.eat() 结果为 C:\pycharm\python.exe D:/python练习程序/第二十四天/继承.py 进老爸 不详 None 在人的类中吃加血药
改进方法一:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Animial: def __init__(self,name,aggr,blood): self.name=name self.blood=blood self.aggr=aggr def eat(self): print('在父类吃回血药') self.blood+=100 class Dog(Animial): def __init__(self,name,aggr,blood,kind): #这种发放可以读取到所有子类的属性 super().__init__(name,aggr,blood)#把父类中共有的属性加到子类使用 self.kind=kind #子类中独有的属性 class Person(Animial): def __init__(self,name,aggr,blood,sex): Animial.__init__(self,name,aggr,blood) self.sex=sex def eat(self): #这样写既可以调用子类方法又可以调用父类里的方法 Animial.eat(self)#使用此方法括号里必须加self print('在人的类中吃加血药') self.blood+=50 jin=Dog('进老爸',100,3,'不详') alex=Person('alex',100,6,None) print(jin.name) print(jin.kind) print(alex.sex) alex.eat()#在人子类中吃加血药 结果为 进老爸 不详 None 在父类吃回血药 在人的类中吃加血药
改进方法二:第二种方法必须在python3以上的版本中使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Animial: def __init__(self,name,aggr,blood): self.name=name self.blood=blood self.aggr=aggr def eat(self): print('在父类吃回血药') self.blood+=100 class Dog(Animial): def __init__(self,name,aggr,blood,kind): #这种发放可以读取到所有子类的属性 super().__init__(name,aggr,blood)#把父类中共有的属性加到子类使用 self.kind=kind #子类中独有的属性 class Person(Animial): def __init__(self,name,aggr,blood,sex): Animial.__init__(self,name,aggr,blood) self.sex=sex def eat(self): #这样写既可以调用子类方法又可以调用父类里的方法 super().eat()#使用此方法括号里不需要加self print('在人的类中吃加血药') self.blood+=50 jin=Dog('进老爸',100,3,'不详') alex=Person('alex',100,6,None) print(jin.name) print(jin.kind) print(alex.sex) alex.eat()#在人子类中吃加血药 结果为 进老爸 不详 None 在父类吃回血药 在人的类中吃加血药
10概念的总结:
父类中没有的属性,在子类中出现叫做派生属性
父类中没有的方法,在子类中出现,叫做派生方法
只要是子类调用对象时,子类中有的名字一定调用子类的,子类中没有的才去父类中去寻找,如果父类也没有就会报错
如果要使用的方法子类和父类都有,而且都想显示,就要使用父类名.方法加到子类方法中,或者是supre().方法加到方法中
11.super的另一种用法:单独在类外面使用:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Animial: def __init__(self,name,aggr,blood): self.name=name self.blood=blood self.aggr=aggr def eat(self): print('在父类吃回血药') self.blood+=100 class Dog(Animial): def __init__(self,name,aggr,blood,kind): #这种发放可以读取到所有子类的属性 super().__init__(name,aggr,blood)#把父类中共有的属性加到子类使用 self.kind=kind #子类中独有的属性 class Person(Animial): def __init__(self,name,aggr,blood,sex): Animial.__init__(self,name,aggr,blood) self.sex=sex def eat(self): #这样写既可以调用子类方法又可以调用父类里的方法 print('在人的类中吃加血药') self.blood+=50 jin=Dog('进老爸',100,3,'不详') alex=Person('alex',100,6,None) print(jin.name) print(jin.kind) print(alex.sex) super(Dog,jin).eat() #只调用父类里的eat方法 结果为 进老爸 不详 None 在父类吃回血药
12多继承:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A:pass class B:pass class C:pass class D(A,B,C):pass
13多继承的执行顺序是从左往右一次执行:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def func(self): print('A') class B: def func(self): print('B') class C: def func(self): print('C') class D(A,B,C): def func(self): print('D') d=D() d.func()#如果D中有会先执行D中的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def func(self): print('A') class B: def func(self): print('B') class C: def func(self): print('C') class D(A,B,C): pass # def func(self): # print('D') d=D() d.func()#如果D中没有会在执行A中的 结果为 A
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: pass # def func(self): # print('A') class B: def func(self): print('B') class C: def func(self): print('C') class D(A,B,C): pass # def func(self): # print('D') d=D() d.func()#如果D、中没有会在执行B中的 结果为 B
14多继承里面的钻石法则:
1.如果D中有先执行D如果没有在执行B,如果B中没有在执行C,如果C中没有在执行A:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def func(self): print('A') class B(A): def func(self): print('B') class C(A): def func(self): print('C') class D(B,C): def func(self): print('D') d=D() d.func() 结果为 D
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def func(self): print('A') class B(A):pass # def func(self): # print('B') class C(A): def func(self): print('C') class D(B,C):pass # def func(self): # print('D') d=D() d.func() 结果为 C:\pycharm\python.exe D:/python练习程序/第二十四天/继承.py C
执行规则如下:
15多继承里的乌龟原则:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class F: def func(self): print('F') class A(F): def func(self): print('A') class B(A):pass # def func(self): # print('B') class E(F): def func(self): print('E') class C(E): def func(self): print('C') class D(B,C): def func(self): print('D') d=D() d.func()
执行规则是:
16多继承里的super()方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def func(self): #第六步 print('A') #第七步 class B(A): def func(self): #第三步 super().func() #第四步 print('B') #第九步 class C(A): def func(self): super().func() #第五步 print('C') #第八步 class D(B,C): def func(self): #第一步 super().func() #第二步 #也是根据节点广度优先原则 print('D') #第十步 d=D() d.func() 结果为 A C B D
17.总结:
新式类中:继承了object的类才称为新式类,广度优先原则
经典类:如果你直接创建一个类在python2的版本中,就是经典类,深度优先原则
super 只是在python3中才存在
super的本质:不是单纯的寻找父类,而是根据调用者的节点位置广度优化顺序进行
18可以使用mor来查看多继承的执行顺序:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def func(self): #第六步 print('A') #第七步 class B(A): def func(self): #第三步 super().func() #第四步 print('B') #第九步 class C(A): def func(self): super().func() #第五步 print('C') #第八步 class D(B,C): def func(self): #第一步 super().func() #第二步 #也是根据节点广度优先原则 print('D') #第十步 d=D() d.func() print(D.mro()) 结果为 A C B D [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]