• 面向对象之继承


    一.继承

    1.1什么是继承

      继承一种新建类的方式,新建的类称之为子类/派生类,被继承的类称之为父类基类超类

    ps:派生类是在继承父类的基础上有一些自己的属性或者技能(有和父类不一样的东西)

    1.2为什么要用继承

      为了减少代码的冗余,重用已有的代码,提高重用性

    1.3python中继承有何特点:

      1.子类可以遗传/重用父类的属性

      2.python中一个子类可以同时继承多个父类

      3.在继承背景下去说,python中的类分为两种:新式类,经典类

    经典类和新式类:
        经典类:经典类只存在与python2中,在书写时没有继承object类,或者继承osject类的子类
        新式类:在python3中全都是新式类,在python2中继承了object的类都叫做新式类

    1.4继承的基本语法

    class Foo:
        pass
    
    class Student(Foo):
        pass
    
    基本语法:class 类名(要继承的类名):
                       

    1.5继承的注意事项

      1.先抽象在继承

      2.继承一个现有的类,扩展或者修改原始的功能

    ps:抽象就是将多个子类中的相同部分进行抽取,形成一个新的类

    二.如何用继承关系解决类和类之间代码冗余的问题

    class OldboyStudent:
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    
    class OldboyTeacher:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
    stu1=OldboyStudent('',38,'male')
    print(stu1.__dict__)
    
    tea1=OldboyTeacher('zhang',18,'male')
    print(tea1.__dict__)

    class OldboyPeople:
        school = 'Oldboy'
    
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class OldboyStudent(OldboyPeople):
        pass
    class OldboyTeacher(OldboyPeople):
        pass
    
    
    stu1=OldboyStudent('',38,'male')
    print(stu1.__dict__)
    
    tea1=OldboyTeacher('zhang',18,'male')
    print(tea1.__dict__)
    继承解决代码冗余(继承后)

    三.在子类派生出的新方法中重用父类的功能集中方式

    3.1指名道姓的方式(__init__)

    class OldboyPeople:
        school = 'Oldboy'
    
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class OldboyStudent(OldboyPeople):
        def __init__(self, name, age, sex, score=0):
            OldboyPeople.__init__(self,name,age,sex)
            self.score = score
    
        def choose_course(self):
            print('%s choosing course' % self.name)
    
    class OldboyTeacher(OldboyPeople):
        def __init__(self,name,age,sex,level):
            OldboyPeople.__init__(self,name,age,sex)
            self.level=level
    
        def score(self,stu,num):
            stu.score=num
    
    
    stu1=OldboyStudent('',38,'male')
    print(stu1.__dict__)
    
    tea1=OldboyTeacher('zhang',18,'male',10)
    print(tea1.__dict__)
    View Code

    ps:1.该方式和继承没有任何关系
       2.访问是类的函数,没有自动传值的效果,需要几个参数就要传几个
       3.当你继承一个现有的类,并且你覆盖 了父类的init方法时,必须在初始化方法的第一行调用父类的初始化方法,并传入父类所需的参数

    3.2方式二super

      在python2中:super(自己的类名,自己的对象).你要调的父类的属性或方法

      在python3中:super().你要调的父类的属性或方法

    ps:1. 严格依赖继承的mro列表
         2. 访问是绑定方法,有自动传值的效果

    ps:mro列表是由类名.mro()产生的一个列表,属性的查找会严格按照这个来执行,即后面的类名一定是前一个的爹

    class OldboyPeople:
        school = 'Oldboy'
    
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class OldboyStudent(OldboyPeople):
        def __init__(self, name, age, sex, score=0):
            super(OldboyStudent,self).__init__(name,age,sex)
            self.score = score
    
        
    
    class OldboyTeacher(OldboyPeople):
        def __init__(self,name,age,sex,level):
            super().__init__(name,age,sex)
            self.level=level
    
    
    
    stu1=OldboyStudent('',38,'male')
    print(stu1.__dict__)
    
    tea1=OldboyTeacher('zhang',18,'male',10)
    print(tea1.__dict__)
    super两种使用方式

    四.属性查找的顺序

    1.在单继承背景下的查找顺序对象->对象的类->父类->......

    class Foo:
        def f1(self):
            print('Foo.f1')
    
        def f2(self):
            print('Foo.f2')
            self.f1() # obj.f1()此处会先找obj自己,然后去所属的类Bar中寻找
    
    class Bar(Foo):
        def f1(self):
            print('Bar.f1')
    
    obj=Bar()
    obj.f2()

    2.在多继承背景下的查找顺序

    4.2.1如果一个子类继承多个分支(多个分支没有共同继承一个非object的类)

    class H:
        x='H'
    class E:
        x='E'
    class F(H):
        x='F'
    class G:
        x='G'
    class B(E):
        x='B'
    class C(F):
        x='C'
    class D(G):
        x='D'
    class A(B,C,D):
        x='A'
    print(A.mro())
    
    #[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.H'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>]
    如果一个子类继承多个分支(多个分支没有共同继承一个非object的类)

     

    查找顺序是对象-->对象的类-->按照从左到右的顺序一个分支一个分支的找完

    4.2.2 菱形继承

    4.2.2.1新式类:广度优先,最后才去找最后的一个类

    class H:
        x='H'
    class E(H):
        x='E'
    class F(H):
        x='F'
    class G(H):
        x='G'
    class B(E):
        x='B'
    class C(F):
        x='C'
    class D(G):
        x='D'
    class A(B,C,D):
        x='A'
    print(A.mro())
    新式类菱形继承

    4.2.2.2经典类(深度优先)深度优先查找,从左往右一个分支一个分支的查找,在第一个定级类就去寻找

    ps:当出现菱形继承时,新式类先深度,当遇到共同父类时就广度

              经典类就是深度优先

  • 相关阅读:
    数学名词的意义
    博主个人介绍
    信仰
    一些优质聚佬的Blog推荐
    本Blog一些声明
    母函数第二弹 之 真正的母函数入门
    November!!!
    首“0”纪念
    关于构造函数解题(母函数入门)
    关于Lucas定理的那些事儿
  • 原文地址:https://www.cnblogs.com/z929chongzi/p/11246974.html
Copyright © 2020-2023  润新知