zoukankan      html  css  js  c++  java
  • [ python ] 继承

    什么是继承:

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

    python 中继承分为:单继承和多继承

    单继承

    class Father1:  # 定义父类
        print('class Father1')
    
    
    class Father2:  # 定义父类
        print('class Father2')
    
    
    class Son1(Father1):  # 单继承,父类:Father1 子类:Son1
        pass
    
    
    class Son2(Father1, Father2):  # 多继承: 父类:Father1, Father2 子类:Son2
        pass

    使用 __bases__ 查看继承:

    __bases__: 查看子类所有的父类。

    print(Son1.__bases__)
    print(Son2.__bases__)
    
    执行结果:
    (<class '__main__.Father1'>,)
    (<class '__main__.Father1'>, <class '__main__.Father2'>)

    继承和抽象(先抽象再继承)

    抽象:抽取类似或者说比较像的部分。
    抽象分为两个层次:
    1. 讲具体的对象进行分类,例如:将奥巴马和梅西这俩对象比较像的部分抽取成类;
    2. 又可以将人、猪、狗这三类比较像的部分抽取为父类(都是动物).

    抽象最主要的作用是划分类别:

    继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构;

    抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类

    继承与重用性

    有如下两个类:人类和鸟类

    class Person:
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
            
            
    class Bird:
        def __init__(self, name, age, kind):
            self.name = name
            self.age = age
            self.kind = kind

    这两个类中的属性,有明显的重复使用,在这种情况下,就可以为这两个类定义一个父类,如下:

    class Animal:    # 抽取出来共同的属性组成父类
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    class Person(Animal):    # 子类继承父类
        def __init__(self, name, age, sex):
            Animal.__init__(self, name, age)    # 需要注意调用父类的方式:父类名.方法名调用
            self.sex = sex    # 子类的派生属性
    
    
    class Bird(Animal):
        def __init__(self, name, age, kind):
            Animal.__init__(self, name, age)
            self.kind = kind    # 子类的派生属性
    
    
    p = Person('hkey', 20, 'male')
    b = Bird('maque', 1, 'maque')
    print(p.name)
    print(b.name)
    
    执行结果:
    hkey
    maque

    用已经有的类建立一个新的类,这样就重用了多数类中重复的属性和方法,不仅可以重用自己的类,也可以继承别人的,这样就大大缩短了软件开发周期。

    派生类

    父类中没有的属性 在子类中出现 叫派生属性
    父类中没有的方法 在子类中出现 叫派生方法

    在继承父类的同时,子类也可以添加自己独有的属性和方法,但是如果定义了和父类重复的属性和方法,那么调用的时候,就会首先调用子类中的属性和方法。

    super函数

    python3 中 super函数的使用

    子类执行父类的方法也可以直接使用super方法,如下例子帮助理解 super 的使用:

    class A:
        def haha(self):
            print('A')
    
    class B(A):
        def haha(self):
            super(B, self).haha()
            print('B')
    
    a = A()
    b = B()
    b.haha()
    print('------')
    super(B, b).haha()
    
    执行结果:
    A
    B
    ------
    A

    对于super函数,我们可以总结如下:

    super函数只存在于python3中
    super().方法名:是寻找父类的方法名并执行;
    在类中方法里可以使用super函数,在外层也可以直接使用super函数寻找父类的方法

    class A:
        def test(self):    # 父类的方法
            print('A')
    
    class B(A):
        def test(self):    # 子类的方法与父类的方法重复,当调用该方法时,首先调用子类的方法
            print('B')
    
    b = B()
    b.test()
    
    执行结果:
    B
    class Animal:
        '''
        人和狗都是动物,所以创造一个Animal父类
        '''
        def __init__(self, name, aggr, hp):
            self.name = name
            self.aggr = aggr
            self.hp = hp
    
        def eat(self):
            print('%s is eating.' % self.name)
    
    
    class Dog(Animal):
        '''
        狗类继承 Animal 类
        '''
        def __init__(self, name, aggr, hp, tooth):
            super(Dog, self).__init__(name, aggr, hp)   # 使用 super 调用父类的方法
            self.tooth = tooth  # 派生属性
        def bite(self, person):
            '''派生方法:狗有咬人的技能'''
            person.hp -= self.aggr
    
    
    class Person(Animal):
        '''
        人类,继承 Animal 类
        '''
        def __init__(self, name, aggr, hp, money):
            super(Person, self).__init__(name, aggr, hp)    # 使用 super 调用父类的方法
            self.money = money  # 派生属性
        def attack(self, dog):
            '''派生方法:人有攻击的技能'''
            dog.hp -= self.aggr
    
    p = Person('kk', 5, 100, 0)
    d = Dog('tt', 10, 50, 1000)
    
    print(p.hp)
    d.bite(p)
    print(p.hp)
    
    # 执行结果:
    # 100
    # 90
    子类派生方法的使用

    1. 通过继承建立了派生类与基类之间的关系,它是一种‘是’的关系,比如白马是马,人是动物。
    2. 当多个类有相同的功能,提取这些相同的功能做成基类(父类),用继承比较好,比如教授是老师。

    class Teacher:
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
        def teach(self):
            print('teaching.')
    
    class Professor(Teacher):
        pass
    
    p1 = Professor('kk', 'male')
    p1.teach()

    多继承

    多继承就是一个子类继承多个父类的方式,这种方式并不多用。

    class A:
        print('A')
    
    class B:
        print('B')
    
    class C(A, B):    # 子类继承两个基类的方式,执行也是从左到右
        pass
    
    
    C()
    
    执行结果:
    A
    B
    C

    继承顺序:
    1. python的类可以继承多个类,java 和 C# 中则只能继承一个类
    2. python的类如果继承了多个类,那么寻找父类的方式有两种:深度优先、广度优先。

        当类是经典类, 多继承的情况下,会按照深度优先方式查找
        当类是新式类, 多继承的情况下,会按照广度优先方式查找

        在python3中全都是新式类

    class A:
        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):
        def test(self):
            print('from D')
    
    class E(C):
        def test(self):
            print('from E')
    
    class F(D, E):
        pass
    
    f1 = F()
    f1.test()
    print(F.mro())
    
    # from D
    # [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

    上面这段代码如下图:

    新式类继承顺序:F -> D -> B -> E -> C -> A
    经典类继承顺序: F -> D -> B -> A -> E -> C

    继承原理

    对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表。

    为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,
    它实际上就是合并所有父类的MRO列表并遵循如下三条准则:

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

    继承小结

    继承的作用:
    1. 减少代码的重用
    2. 提高代码可读性
    3. 规范编程模式

    几个名词:
    抽象:抽象即抽取类似或说比较像的部分。是一个从具体到抽象的过程。
    继承:子类继承父类的方法和属性
    派生:子类在父类方法和属性的基础上产生了新的方法和属性

  • 相关阅读:
    C语言复习---二维数组和二级指针的关系:没关系,别瞎想(重点)
    数据结构(二)栈与队列---回溯法之八皇后问题
    数据结构(二)栈与队列---递归之汉罗塔
    数据结构(二)栈与队列---栈的应用(递归和分治思想)
    数据结构(二)栈与队列---队列
    chmod 权限777 是什么意思(Unix和Linux的各种操作系统下)
    C#:基于WMI查询USB设备
    Eclipse中web项目部署至Tomcat步骤
    CSS设置DIV背景色渐变显示
    通过[蜘蛛协议]Robots.txt禁止搜索引擎收录的方法
  • 原文地址:https://www.cnblogs.com/hukey/p/9888439.html
Copyright © 2011-2022 走看看