学习python课程第二十二天

一 .   类的继承与派生 : 

  1. 什么是继承:

    在程序中继承是一种新建子类的方式, 新创建的类称之为子类,或者派生类.

    被继承的类称之为父类,

    继承描述的是一种遗传关系, 子类可以重用父类的属性.

  2. 为何要用继承 :

    继承可以减少类与类之间代码冗余的问题.

  3. 如何继承 :

    先抽象,再继承

    抽象 :抽取出比较像的部分.. 最主要的作用是划分类别 (可以隔离关注点, 降低复杂度.)

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

    出抽象的结构

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

  示例 :

    #  在python中继承的特点 : 有单继承 和 多继承

 

    class Parent1:

      pass

    class Parent2:

      pass

    class Sub1(Parent1):

      pass

    class Sub2(Parent1,Parent2):

      pass

  print(Sub1.__bases__)  # 查看它的基础,基本

  print(Sub2.__bases__)

      

  python2 与 python3中,继承上的区别:

  新式类 : 但凡继承object类的子类, 以及该子类的子子类...都称之为新式类.

  

  经典类 : 没有继承object类的子类, 以及该子类的子子类...都称之为经典类.

  

  只有在python2中才区分新式类与经典类.  (在python中也写上object,这个程序也可以在python2中兼容)

  

  4. 基于继承解决类与类代码冗余的问题 :

   在子类派生出的新功能中,如何重用父类的功能:

   方式一:    指名道姓的访问某一个类中的函数,与继承无关,

    class OldboyPeople:      # 存放两个类似的相同属性.  (父类)

      school = 'Oldboy'   

      def  __init__(self,name,age,gender):

        self.name = name

        self.age = age

        self.gender = gender

    

    class OldboyStudent(OldboyPeople)     # 学生的类

      def  choose_course(self):

        print('%s  正在选课' %self.name)

    class  OldboyTeacher(OldboyPeople):

      def  __init__(self,name,age,gender,level.salary):

        OldboyPeople.__init__(slef,name,age,gender)  #  指名道姓的找到父类里相同的属性

        self.level = level

        self.salary = salary

      def  score(self,stu,num):

        stu.num = num

        print('老师%s给学生%s打分%s' %(self,name,stu.name,num))

    

  5.  在单继承的背景下属性的查找:

    在单继承背景下, 无论是新式类,还是经典类, 属性查找顺序都一样.

    顺序:    先 obj ---> 类 ---> 父类 --->......

    class   Foo:

      def f1(self):

        print('Foo 1')

      def f2(self):

        print('Foo  2')

        self.f1()    #obj.f1()

    class Bar(Foo):

      def  f1(self):

        print('Bar  f1')  # 打印这个结果

  obj = Bar()

  obj.f2()

  

  6. 在多继承背景下, 如果一个子类继承了多个分支,但是多个分支没有汇聚到一个非object类.

    无论新式类和经典类查找顺序都一样 : 

    顺序:   会按照从左到右的顺序一个分支一个分支的查找下去 

      A -->B-->E-->C-->F--D  最后在找object

    class  F:

     pass

    class  E:

     pass

    class  B(E):

     pass

    class  C(F):

     pass

    class  D:

     pass

    class  A(B,C,D):

     pass

  在多个继承背景下, 如果一个子类继承了多个分支,但是多个分支最终汇聚到一个非object类 (菱形继承问题)

    

  新式类的查找方式 : 广度优先查找  obj-->A-->B-->E-->C-->F-->D-->G-->object

  经典类的查找方式 : 深度优先查找  obj-->A-->B-->E-->G-->C-->F-->D

  

   这个查找顺序都是基于C3算法得来的结果,

  C3 算法在python3里有一个内置的方法,xx . mro() 在mro列表中存放着C3算法的结果, 它是在定义类的时候就

  开始计算了.

  不管是单继承还是多继承或者是菱形继承, 都是按照C3算法的mro里的结果列表的顺序来查找.

  

  

  

  

  7. 用super方法来重用父类的功能.

  

  super(OldboyTeacher). 在python3中super可以不传参数,调用该函数会得到一个特殊的对象,该对象是专门用来

    访问父类中的属性.

  强调 : super会严格参照当前类的mro列表依次查找属性.

  # 在子类派生出的新功能中, 如何重用父类的功能:

    方式2 :

    

    class OldboyPeople:

      school = 'oldboy'

      def __init__(self,name,age,gender):

        self.name = name

        self.age = age

        self.gender = gender

      

    class OldboyTeacher(OldboyPeople):

      def  __init__(self,name,age,gender,level,salary):

        super(OldboyTeacher,self).__init__(name,age,gender)    #super本身不用传参数

        self.level = level

        self.salary = salary

  注意 :  两种方式都可以用,但是最好不要两种方式混着用.

  

  总结 : 一般在搭建框架的时候才用到多继承, 继承这个方式以后能不用就不用, 好处确实是能减少代码冗余,

  但是它把子类和父类的耦合加大. 程序的可读性变差.   继承可以用,但是一般在单继承的场景下再用.

    

原文地址:https://www.cnblogs.com/lvyipin1/p/9838005.html