python之面向对象继承

一、面向对象之继承

  1. 面向对象三大特性

    面向对象三大特性:封装,继承,多态

  2. 继承

    • 定义

      ​ 如果一个类别A“继承自”另一个类别B就把这个A称为“B的子类”或“B的派生类”,而把B称为“A的父类”也可以称为“B是A的基类或超类”。

      ​ 继承可以使的子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。

      ​ 在子类继承父类的同时,可以重新定义某些属性,并重写某些方法(即覆盖父类的原有属性和方法)使其获得与父类不同的功能,也可为子类追加新的属性和方法

    • 特点

      1. 增加了类的耦合性(耦合性不宜多,易精)
      2. 减少代码重复性
      3. 是的代码更加规范化,合理化
    • 分类

      继承可以分为单继承多继承

      在python2中x版本中存在两种类:

      ​ 一个叫经典类,python2.2之前一直使用的使经典类,经典类在基类的根什么都不写

      ​ 一个叫新式类,python2.2之后出现了新式类,新式类在基类的根是object类

      python3中使用的都是新式类,如果基类谁都不继承,那这个类默认继承object

  3. 单继承

    • 类名,对象执行父类方法

      • 从类名执行父类的属性和方法

        class Animal(object):
            live = '有生命的'
            def __init__(self,name,age,sex):
                self.name = name
                self.age = age
                self.sex = sex
            def eat(self):
                print(f'self--->{self}')
                print('动物需要进食')
        class Person(Animal):
            pass
        
        print(Person.live)	# 有生命的
        print(Person.__dict__)
        # {'__module__': '__main__', '__doc__': None}
        Person.eat(12)
        # self--->12
        # 动物需要进食
        
      • 从对象执行父类的属性和方法

        class Animal(object):
            live = '有生命的'
            def __init__(self,name,age,sex):
                self.name = name
                self.age = age
                self.sex = sex
            def eat(self):
                print(f'self--->{self}')
                print('动物需要进食')
        class Person(Animal):
            pass
        p1 = Person('dsb',21,'laddy_boy')
        print(p1.__dict__)
        # {'name': 'dsb', 'age': 21, 'sex': 'laddy_boy'}
        print(p1.live)
        # 有生命的
        # self---><__main__.Person object at 0x000001E8FC22F4E0>
        p1.eat()
        # 动物需要进食
        

        注意:子类以及子类对象只能调用父类的属性以及方法,不能操作(增删改)

    • 执行顺序

      对象查找顺序先从对象空间找名字,再到子类找名字,然后去父类找名字

    • 同时执行类以及父类方法

      • 方法一

        class Animal:
            live = '有生命的'
            def __init__(self,name,age,sex):
                self.name = name
                self.age = age
                self.sex = sex
            def eat(self):
                print('动物都需要进食')
        class Person(Animal):
            def __init__(self,name,age,sex,hobby):
                Animal.__init__(self,name,age,sex)#调用Animal的__init__方法,当Person实例化时,将name,age,sex传递给Animal
                self.hobby = hobby
            def eat(self):
                print('人类需要进食')
        p1 = Person('铁憨憨',23,'男','锤人')
        print(p1.__dict__)
        # {'name': '铁憨憨', 'age': 23, 'sex': '男', 'hobby': '锤人'}
        

        在对象的空间中调用父类的__init__方法,通过子类的实例化将父类__init__所需的参数传进去。

      • 方法二

        class Animal:
            live = '有生命的'
            def __init__(self,name,age,sex):
                self.name = name
                self.age = age
                self.sex = sex
            def eat(self):
                print('动物都需要进食')
        class Person(Animal):
            def __init__(self,name,age,sex,hobby):
                super().__init__(name,age,sex)
                self.hobby = hobby
            def eat(self):
                print('人类需要进食')
                super().eat()
        p1 = Person('铁憨憨',23,'男','锤人')
        p1.eat()
        # 人类需要进食
        # 动物都需要进食
        

        通过super().__init__的方式在对象空间中添加父类的属性

  4. 多继承

    class God:
        def __init__(self,name):
            self.name = name
        def fly(self):
            print('会飞')
        def climb(self):
            print('神仙累了也需要爬树')
    class Monkey:
        def __init__(self,sex):
            self.sex = sex
        def climb(self):
            print('爬树')
    class MonkeySun(God,Money):
        pass
    sun = MonkeySun()
    sun.climb()
    # 神仙累了也需要爬树
    
    • 经典类的多继承

      虽然在python3中已经不存在经典类了. 但是经典类的MRO最好还是学⼀学. 这是⼀种树形结构遍历的⼀个最直接的案例,代码如下:

      class A:
          pass
      class B(A):
          pass
      class C(A):
          pass
      class D(B, C):
          pass
      class E:
          pass
      class F(D, E):
          pass
      class G(F, D):
          pass
      class H:
          pass
      class Foo(H, G):
          pass
      

      继承关系图如下:

      在经典类中采⽤的是深度优先,遍历方案。⼀条路走到头,然后再回来,继续找下⼀个。

    • 新式类的多继承

      代码如下:

      class A:
          pass
      
      class B(A):
          pass
      
      class C(A):
          pass
      
      class D(B, C):
          pass
      
      class E:
          pass
      
      class F(D, E):
          pass
      
      class G(F, D):
          pass
      
      class H:
          pass
      
      class Foo(H, G):
          pass
      print(Foo.mro())
      
      • mro序列

        MRO是一个有序列表L,在类被创建时就计算出来。
        通用计算公式为:

        mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )
        (其中Child继承自Base1, Base2)
        

        如果继承至一个基类:class B(A)
        这时B的mro序列为

        mro( B ) = mro( B(A) )
        = [B] + merge( mro(A) + [A] )
        = [B] + merge( [A] + [A] )
        = [B,A]
        

        如果继承至多个基类:class B(A1, A2, A3 …)
        这时B的mro序列

        mro(B) = mro( B(A1, A2, A3 …) )
        = [B] + merge( mro(A1), mro(A2), mro(A3) ..., [A1, A2, A3] )
        = ...
        

        计算结果为列表,列表中至少有一个元素即类自己,如上述示例[A1,A2,A3]。merge操作是C3算法的核心。

      • 表头和表尾

        表头:
          列表的第一个元素

        表尾:
          列表中表头以外的元素集合(可以为空)

        示例
          列表:[A, B, C]
          表头是A,表尾是B和C

      • 列表之间的+操作

        +操作:

        [A] + [B] = [A, B]
        (以下的计算中默认省略)
        ---------------------

        merge操作示例:

        如计算merge( [E,O], [C,E,F,O], [C] )
        有三个列表 :  ①      ②          ③
        
        1 merge不为空,取出第一个列表列表①的表头E,进行判断                              
           各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表
        2 取出列表②的表头C,进行判断
           C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除
           merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )
        3 进行下一次新的merge操作 ......
        --------------------- 
        

        继承关系图如下:

        计算mro(A)方式:

        mro(A) = mro( A(B,C) )
        
        原式= [A] + merge( mro(B),mro(C),[B,C] )
        
          mro(B) = mro( B(D,E) )
                 = [B] + merge( mro(D), mro(E), [D,E] )  # 多继承
                 = [B] + merge( [D,O] , [E,O] , [D,E] )  # 单继承mro(D(O))=[D,O]
                 = [B,D] + merge( [O] , [E,O]  ,  [E] )  # 拿出并删除D
                 = [B,D,E] + merge([O] ,  [O])
                 = [B,D,E,O]
        
          mro(C) = mro( C(E,F) )
                 = [C] + merge( mro(E), mro(F), [E,F] )
                 = [C] + merge( [E,O] , [F,O] , [E,F] )
                 = [C,E] + merge( [O] , [F,O]  ,  [F] )  # 跳过O,拿出并删除
                 = [C,E,F] + merge([O] ,  [O])
                 = [C,E,F,O]
        
        原式 = [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])
            = [A,B] + merge( [D,E,O], [C,E,F,O],   [C])
            = [A,B,D] + merge( [E,O], [C,E,F,O],   [C])  # 跳过E
            = [A,B,D,C] + merge([E,O],  [E,F,O])
            = [A,B,D,C,E] + merge([O],    [F,O])  # 跳过O
            = [A,B,D,C,E,F] + merge([O],    [O])
            = [A,B,D,C,E,F,O]
        
原文地址:https://www.cnblogs.com/yaoqi17/p/11159737.html