继承的另一种使用方式。。。

继承的另一种使用方式 *****

  --1、之前讲的有继承关系的类都是我们新建的,不常用

  --2、最常用的是直接继承一个已经存在的类

      --当你想要创建一个新的类时 ,发现这个类中的一些功能在另外的某个类中存在

        我们就没必要从头开始重写这些功能,可以直接继承已有的类,然后做补充

  注:假如我们时需要父类中的初始化属性,并且还需要添加点属性,那么必须覆盖父类的__init__方法

      先通过super()方法重用父类属性,再添加自己新增的初始化属性或者方法

super()的问题以及mro列表

python中支持多继承:一个子类可以同时拥有多个父类

  优点:可以让代码变得更加灵活

  缺点:属性查找顺序需要通过C3算法来确定

多继承时如果多个父类出现相同名称的属性或者函数

查找的顺序要根据mro列表来确定

总结:super()在访问父类属性时,是按照mro列表一层一层往上找的

eg:(哪个类的对象调用,就遵循这个类的mro列表查找顺序)

class A:
    def test(self):
        print('from A')
        super().test()   # A的父类应该是object
                        # 但是super()是根据mro列表访问顺序来查找的
class B:                # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
    def test(self):      # 对与C来说mro列表B在A之后,所以A里面的super访问到的就是B里的函数
        print('from B')  
class C(A,B):
    # def test(self):
    #     print('from C')
    pass

c = C()
c.test()
print(C.mro())

组合

 组合指的是一个类把另一个类的对象作为自己的属性  -->这就叫做组合

组合与继承的区别:

相同点:都是为了重用代码,减少代码的冗余

不同点:

  --组合      把另一个类的对象作为自己属性的类产生的对象,可以通过对象点出另一个类的对象再点出

        另一个对象的属性和行为

  --继承  一个类继承另一个类,那么这个类的对象可以点出被继承的类中的属性和方法

组合的例子:

class A:

  def __init__(self):

    pass

class B:

  def __init__(self,obj):

    self.obj = obj

a = A()  # a可以使用A类中的属性和方法

b = B(a)     b可以使用B中的属性和方法   b.obj就是a对象也可以使用A类中的属性和方法了

菱形继承问题

新式类:

  直接或者间接继承object类(基类)的类称为新式类

经典类:

  没有直接或者间接继承object类(基类)的类称为经典类

菱形继承:

  指的是一个子类有多个父类,并且这些多个父类又继承同一个父类

菱形继承产生的问题:

  如果多个父类有相同名称的属性或者是相同名称的行为,那么属性查找的顺序就不能按之前的顺序来查找

  会通过C3算法得出一个mro列表,可以通过子类直接点出mro方法来查看mro列表

  属性查找顺序是根据mro列表来查找

接口与抽象类

抽象类

抽象:指的是不清楚的,不具体的,看不懂

抽象方法

  指的是 没有具体函数体的方法,

  用@abc.abcstractmethod装饰器 -->子类继承它的时候必须明确抽象方法下面的函数体

抽象类及特点

  定义:如果类中具备抽象方法,那么这个类就称为抽象类

  特点:不能直接实例化,必须有子类覆盖了所有抽象方法之后才能实例化子类

接口

 接口理解:

  当一个对象的类里面有其他类对象作为方法,并且类方法内其他类对象具有一系列方法 # (按组合理解)

  那么想要执行类的方法就必须把其他类产生的对象传进去,

  并且这个其他类必须按照类里面的方法来定义自己的方法

所以接口就是一套协议规范

具体表现形式:类中有一堆函数,但是只明确了函数的名称,没有明确函数的具体实现

优点:

#1、使用接口可以提高程序的扩展性

#2、只要对象按照接口规定方法来实现,使用者就可以无差别使用所有对象

问题:

  如果接口的子类没有实现接口中的方法,那是没有任何意义的

抽象类之所以出现的意义

  就是通过抽象类来强行限制子类必须覆盖所有抽象方法

class PC:
    def connect_device(self,device):
        device.open()
        device.working()
        device.close()

class USB:
  @abc.abcstractmethod      # usb想要使用电脑对象中的功能,就必须按照PC类中方法下面连接设备的方法来定义
    def open(self):    # 只要满足PC类方法下面的几个方法,那么把usb对象传进去就能被识别
        pass           # 而这个只有方法,没有函数体的就被称为接口,主要作用是作为以重协议规定
  @abc.abcstractmethod
    def working(self):  # 让其他想要使用电脑对象中功能的设备照着这个规定来定义自己的类
        pass
    @abc.abcstractmethod 
    def close(self):
        pass

pc = PC()   # 电脑对象
usb = USB()   # usb对象 (不能实例化,为了下面理解使用功能,会报错)
pc.connect_device(usb)  # 这样就可以使用电脑中的功能了

接口与抽象类的区别

  接口中的所有方法都是抽象方法,而有一个抽象方法的类就是抽象类

鸭子类型

定义:

   指的是一个对象如果长得像鸭子(属性/特征),叫声像鸭子,走路像鸭子(方法/行为),

   那么它就是鸭子,就可以把他当鸭子使用

意思是:

  如果你的属性的行为都是按照接口的规范定义的,那么即便你不是接口的子类,

  那么(电脑)中的方法你依旧可以使用

原文地址:https://www.cnblogs.com/hesujian/p/10883808.html