26.面向对象的三个基本特征之继承

面向对象的三个基本特征是:继承、多态,封装。这里讲继承。

继承:是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类由称为基类或超类,新建的类称为派生类或子类

查看父类:类名.__banses__  可以查看该类的父类

如果一个类没有继承任何类,使用类名.__banses__ 返回的是class 'object'(对象类)   在python3中,一个类没有继承任何父类,就默认继承class 'object'(对象类)

单继承:

使用继承: class 子类名(父类名)   就可以在子类中使用父类的属性

class animal:
    def __init__(self,name,kind):
        self.name=name
        self.kind=kind
    def eat(self):
        print('%s正在吃'%self.name)
    def drink(self):
        print('%s正在喝'%self.name)
    def look_door(self):
        print('%s正在看门'%self.name)
class Dog(animal):
    def look_door(self):
        print('%s正在看门'%self.name)
class Bird(animal):
    def egg(self):
        print('%s正在下蛋'%self.name)    
wangwang=Dog('大黄','金毛')
jiji=Bird('星期五','鹦鹉')    
jiji.egg()    #调用自己类的方法
wangwang.look_door()  #调用自己类的方法

执行结果:

星期五正在下蛋
大黄正在看门

子类中的方法与父类中的方法同名,当子类自己有方法时,就不会去父类中寻找方法,被调用时会使用子类自己的方法。

 

派生:在父类属性之外又添加属于自己类的属性

如果子类和父类都拥有__init__()方法,子类就无法继承父类中的__init__(),只调用自己的__init__()

因此想要继承父类的__init__(),还想添加属于自己类的属性,
就要在子类__init__()中引用父类的__init__(),代码如下:

class Animal:
    def __init__(self,name,kind):
        self.name=name
        self.kind=kind
    def eat(self):
        print('%s正在吃'%self.name)
    def drink(self):
        print('%s正在喝'%self.name)

class Dog(Animal):
    def __init__(self,name,kind,high):
        Animal.__init__(self,name,kind)    #引用父类的__init__()
        self.high=high                  #派生属性,添加属于自己类的方法
    def look_door(self):             #派生方法,父类没有而子类有的方法
        print('%s正在看门'%self.name)
s=Dog('大黄','金毛','50cm')
print(s.high)

派生属性:父类中没有的属性,在子类中出现,就叫做派生属性

派生方法:父类中没有的方法在子类中出现

class Animal:
    def __init__(self,name,kind):
        self.name=name
        self.kind=kind
    def eat(self):
        print('%s正在吃'%self.name)
    def drink(self):
        print('%s正在喝'%self.name)

class Dog(Animal):
    def drink(self):
        Animal.drink(self)           #调用子类中的函数,注意参数一定是self
        print('这是新添加的父类没有的语句')   #子类函数新添加的语句
s=Dog('大黄','金毛')
s.drink()

 

只要是子类的对象调用 ,子类中有的名字,一定用子类的,子类中没有才找父类的

在子类函数中调用父类函数的方法,同时又给方法添加新属性;不仅能使用父类中的函数,还能使用自己拓展的属性

 

super

在上面的代码中,子类中有__init__() ,且父类中也有__init__(),想让子类使用父类中的__init__,就可以使用:

父类名.__init__(self,父类的属性名)

这样子类就可以使用父类中的属性。

还可以使用super关键字来完成此功能。具体格式为:super().__init__(name,kind)

如果在子类中使用super()方法,就意为这去找父类的方法,使用super就可以找到父类,区别就是不用传递self作为参数

代码如下:

class Animal:
    def __init__(self,name,kind):
        self.name=name
        self.kind=kind
    def eat(self):
        print('%s正在吃'%self.name)
    def drink(self):
        print('%s正在喝'%self.name)
class Dog(Animal):
    def __init__(self,name,kind,high):
        super().__init__(name,kind)    #使用super引用父类的__init__(),参数与父类__init__的参数相同
        self.high=high
    def drink(self):
        print('%s正在喝'%self.name)
s=Dog('大黄','金毛','50cm')
print(s.high)

super只在新式类中有(在pyhton3中所有的类都是新式类)

super不仅可以在类里使用,也可以在类外使用:super(Dog,s).drimk() 就可以执行到父类中的drink方法(super(Dog,s)可以找到Dog类的父类,然后执行drink方法)

super的本质:在多继承中,不是单纯的找父类,而是根据调用者的节点位置的广度优先顺序来的

多继承:

一个类继承多个类就是多继承。如下:类D继承了ABC多个类

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中有自己的func()方法,因此函数的执行结果为d)

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
d=D()
d.func()

执行结果:

a  (该段代码中,类D中没有自己的func()方法,就需要使用所继承的父类中的func(),因为类A写在最前面,因此有限执行类A的func()方法,代码最后打印A)

钻石继承问题:

如果两个类所继承的类相同,先广度寻找,再深度寻找;继承的类不相同,就先深度寻找,再广度寻找。

多继承中,子类的对象调用一个方法,默认就是就近原则,找的顺序为:

新式类中,类的继承顺序采用的是广度优先算法
标准类中,类的继承顺序采用的是深度优先算法

在python2.7中,新式类与经典类共存,新式类要继承object,Python3中,只有新式类,默认继承object

类名.mro()   使用该语句可以查看该类所继承的父类的寻找顺序, mro方法只在新式类中存在

 

posted @ 2020-10-22 21:41  maday  阅读(164)  评论(0)    收藏  举报