zoukankan      html  css  js  c++  java
  • 类的继承

    类的继承

    一、什么是面向对象的继承?

    • 继承是一种创建新类的方式,新建的类可称为子类或者派生类,父类可称基类或者超类
    • python支持多继承,其他语言不支持多继承
    • 继承可以使得子类别具有父类别的各种属性和方法。
    • 在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。

    继承的优点有哪些?

    • 增加了类的耦合性
    • 减少了重复代码
    • 减少了重复代码

    多继承的缺点:

    • 违背了人的思维习惯:继承表达的是一种什么是什么的关系
    • 代码可读性会变差
    • 不推荐使用多继承,应该使用Mixins(变相的多继承)

    例子

    class Father:
        print('我是你的爸爸,是你的基类')
    
    class Mother:
        print('我是你的妈妈,也是你的基类')
    
    '''
    语法:
    class 类名(要继承的类名1,要继承的类名2):
        pass
    '''
    
    #单继承
    class Son1(Father):
        pass
    
    #多继承
    class Son2(Father,Mother):
        pass
    

    二、继承的分类

    继承:可以分单继承,多继承

    在python2x版本中存在两种类.:
      ⼀个叫经典类. 在python2.2之前. ⼀直使⽤的是经典类. 经典类在基类的根如果什么都不写.
      ⼀个叫新式类. 在python2.2之后出现了新式类. 新式类的特点是基类的根是object类。
    python3x版本中只有一种类:
    python3中使⽤的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object

    object:是一个内置的类,里面包含很多功能-

    三、单继承详细介绍

    3.1、属性查找顺序

    代码示例:

    #
    class A:
        def f1(self):
            print('f1')
        def f2(self):
            print('f2')
            self.f1()
    #继承A类
    class B(A):
    
        def f1(self):
            print('Bf1')
    #实例化对象
    obj = B()
    obj.f2()
    #输出
    f2
    Bf1
    
    image-20200913223339637

    3.2、那么怎么让3.1中self.f1调用父类的f1函数而不是调用子类的f1函数呢?

    看代码:

    class A:
    
        def f1(self):
            print('f1')
    
        def f2(self):
            print('f2')
            ######方法一
            A.f1(self)
            #self.f1()
    
    class B(A):
    
        def f1(self):
            print('Bf1')
    
    obj = B()
    obj.f2()
    
    

    四、多继承详细介绍

    4.1、多继承的菱形继承

    ​ 大多数面向对象语言都不支持多继承,而在Python中,一个子类是可以同时继承多个父类的,这固然可以带来一个子类可以对多个不同父类加以重用的好处,但也有可能引发著名的菱形问题(或称钻石问题,有时候也被称为“死亡钻石”),菱形其实就是对下面这种继承结构的形象比喻

    image-20200913230246548

    出现这种问题的原因是,当B、C都继承了A(AB都重现改方法),D继承了B、C,可是D没有重写改方法!那么D继承的是B的还是C的呢?

    class A(object):
        def test(self):
            print('from A')
    
    class B(A):
        def test(self):
            print('from B')
    
    class C(A):
        def test(self):
            print('from C')
            
    方式一:
    class D(B,C):
        pass
    
    obj = D()
    obj.test() # 结果为:from B
    
    方式二:
    class D(C,B):
        pass
    
    obj = D()
    obj.test() # 结果为:from C
    
    #这是为什么呢?看方法解析就知道啦!顺序看mro的顺序即可!
    print(D.mro())
    [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    
    4.2、多继承的属性查找顺序原理

    ​ 1.子类会先于父类被检查
    ​ 2.多个父类会根据它们在列表中的顺序被检查
    ​ 3.如果对下一个类存在两个合法的选择,选择第一个父类

    ​ 4.由对象发起的属性查找,会从对象自身的属性里检索,没有则会按照对象的类.mro()规定的顺序依次找下去,

    ​ 5.由类发起的属性查找,会按照当前类.mro()规定的顺序依次找下去(python2、3的mro算出来的顺序是不一样的)

    4.3、深度优先和广度优先
    class E:
        def test(self):
            print('from E')
    
    
    class F:
        def test(self):
            print('from F')
    
    
    class B(E):
        def test(self):
            print('from B')
    
    
    class C(F):
        def test(self):
            print('from C')
    
    
    class D:
        def test(self):
            print('from D')
    
    
    class A(B, C, D):
        # def test(self):
        #     print('from A')
        pass
    
    
    print(A.mro())
    '''
    [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class 'object'>]
    '''
    
    obj = A()
    obj.test() # 结果为:from B
    # 可依次注释上述类中的方法test来进行验证
    

    4.4 Pyton Mixins机制

    Mixins机制核心

    • 就是在多继承的背景下尽可能的 提升多继承的可读性
    • 让多继承满足人的思维习惯:什么是什么

    使用Mixin类实现多重继承要非常小心

    • 首先它必须表示某一种功能,而不是某个物品,python 对于mixin类的命名方式一般以 Mixin, able, ible 为后缀
    • 其次它必须责任单一,如果有多个功能,那就写多个Mixin类,一个类可以继承多个Mixin,为了保证遵循继承的“is-a”原则,只能继承一个标识其归属含义的父类
    • 然后,它不依赖于子类的实现
    • 最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。(比如飞机照样可以载客,就是不能飞了)

    加上Mixin,规范!

    class Vehicle:  # 交通工具
        pass
    
    
    class FlyableMixin:
        def fly(self):
            '''
            飞行功能相应的代码        
            '''
            print("I am flying")
    
    
    class CivilAircraft(FlyableMixin, Vehicle):  # 民航飞机
        pass
    
    
    class Helicopter(FlyableMixin, Vehicle):  # 直升飞机
        pass
    
    
    class Car(Vehicle):  # 汽车
        pass
    
    # ps: 采用某种规范(如命名规范)来解决具体的问题是python惯用的套路
    

    五 、派生与方法重用

    方法一:“指名道姓”地调用某一个类的函数

    此方法不继承也可以调用其他类的属性

    People.init(self,name,age,sex)加上这个即可,想要调用函数,还是得继承

    class People:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def f1(self):
            print(F'{self.name}是沙雕')
    
    class hh():
        def __init__(self,name,age,sex,level,love):
            People.__init__(self,name,age,sex)
            self.level = level
            self.love = love
    
    obj = hh('张三',18,'男',3500,'钱')
    print(obj.name)
    

    方法二:super()

    • 调用super()会得到一个特殊的对象,该对象会参照当前类的mro,去当前类的父类中找属性
    • 在python3中直接调用即可,python2-->super(当前类名称,self)
    class People:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        def f1(self):
            print(F'{self.name}是沙雕')
    
    #调用super()会得到一个特殊的对象,该对象会参照当前类的mro,去当前类的父类中找属性
    class hh(People):
        def __init__(self,name,age,sex,level,love):
            super().__init__(name,age,sex)
            self.level = level
            self.love = love
    
    obj = hh('张三',18,'男',3500,'钱')
    print(obj.name)
    
  • 相关阅读:
    D3.js:交互式操作
    D3.js:Update、Enter、Exit
    D3.js:动态效果
    D3.js:完整的柱形图
    D3.js:坐标轴
    D3.js
    ES 6 : 数组的扩展
    ES 6 : Math对象的扩展
    拉勾网企业图片列表效果
    拉勾网图片切换效果
  • 原文地址:https://www.cnblogs.com/hsyw/p/13664348.html
Copyright © 2011-2022 走看看