zoukankan      html  css  js  c++  java
  • 继承与派生

    1、什么是继承"
    继承是一种新建类的方式,新建的类称之为子类或派生类,继承的父类称之为基类或超类
    -在python中一个子类可以继承多个父类 ******
    -在其他语言中,一个子类只能继承一个父类
    2、继承的作用
    减少代码的冗余
    3、如何实现继承?
    1)先确认谁是子类,谁是父类
    2)在定义子类时,子类名(父类名)
    #父类
    class Father1:
        x = 1
        pass
    class Father2:
        pass
    class Father3:
        pass
    
    #子类
    class Sub(Father1, Father2, Father3):
        pass
    
    #子类.__bases__查看父类
    print(Sub.__base__) #<class '__main__.Father1'>
    print(Sub.x)  #1

    -如何寻找到继承的关系:

      -确认谁是子类:

        hcy对象----->人子类------>动物父类

        猪坚强对象----->猪子类-------->动物父类

        哈士奇对象------->狗子类------->动物父类

      -确认谁是父类

        -动物类是父类

          -抽取对象之间相似的部分,总结出来

          -抽取类之间相似的部分,总结出父类

    #oldboy人类
    class OldboyPeople:
        school = 'oldbay'
        country = 'china'
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    #老师类
    class OldboyTeacher(OldboyPeople):
        #老师修改分数
        def change_score(self):
            print(f'老师{self.name}正在修改分数。。。。')
    
    #学生类
    class OldboyStudent(OldboyPeople):
        #学生选课系统
        def choose_course(self):
            print(f'学生『{self.name}正在选择课程。。。')
    
    stu1 = OldboyStudent('YJG', 50, 'female')
    print(stu1.school, stu1.name, stu1.age, stu1.sex)
    tea1 = OldboyTeacher('大脸', 75, 'female')
    print(tea1.school, tea1.name, tea1.age, tea1.sex)

    注意:中程序的执行顺序是由上到下,父类必须定义在子类的上方

    - 在继承背景下,对象属性的查找顺序:

      1.先从对象自己的名称空间中查找

      2.对象中没有,从子类的名称空间中查找

      3.子类中没有,从父类的名称空间中查找,若父类没有,则会报错!

    #父类
    class Goo:
         x =10
         pass
    
    #子类
    class Foo(Goo):
         x =100
         pass
    foo_obj= Foo()
    #1)
    # foo_obj.x = 1000
    print(foo_obj.x)        #100
    print('对象的名称空间:', foo_obj.__dict__)   # {}
    print('子类的名称空间:', Foo.__dict__)  #{'__module__': '__main__', 'x': 100, '__doc__': None}
    print('父类的名称空间:', Goo.__dict__)     #{'__module__': '__main__', 'x': 10, '__dict__': <attribute '__dict__' of 'Goo'
    print('对象的名称空间:', foo_obj.__dict__)   #{}
    #2)
    foo_obj.x = 1000
    print(foo_obj.x)        #1000    对象添加属性的操作,并不是修改了子类的属性
    print('对象的名称空间',foo_obj.__dict__)   #{'x': 1000}
    print('子类的名称空间',Foo.__dict__ )      #{'__module__': '__main__', 'x': 100, '__doc__': None}
    print('父类的名称空间', Goo.__dict__)      #{'__module__': '__main__', 'x': 10, '__dict__': <attribute '__dict__'...
    print('对象的名称空间', foo_obj.__dict__)  #{'x': 1000}

    派生:

      指的是子类继承父类的属性方法,并且派生出自己独有的属性与方法

      若子类中的方法名与父类的相同,优先用子类的

    #父类
    class Foo:
        def f1(self):
            print('from Foo.f1...')
        def f2(self):   #self ---->bar_obj
            print('from Foo.f2...')
            #bar_obj.f1()---->对像自己找---->Bar ----->Foo
            self.f1()
    
    #子类
    class Bar(Foo):
    
        #相当于重写
        def f1(self):
            print('from Bar.f1...')
        def func(self):
            print('from Bar.func...')
    
    bar_obj = Bar()
    bar_obj.f1()    #from Bar.f1...
    bar_obj.func()  #from Bar.func...
    bar_obj.f2()    #from Foo.f2...
                    #from Bar.f1...
    
    #派生后继承关系查找验证:
    bar_obj = Bar()
    bar_obj.f2()
    '''
    结果1: 
        from Foo.f2...
        from Bar.f1...
    '''

    派生与继承:

    子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法。

    解决问题:子类重用父类的属性,并派生出新的属性

      两种方式:

        1.直接引用父类的__init__为其传参,并添加子类的属性

        2.通过super来指向父类的属性

          -super()是一个特殊的类,调用super得到一个对象,该对象指向父类的名称空间

        注意:使用哪一种都可以,但不能两种方式混合使用

    class People:
        school = '清华大学'
        def __init__(self, name, sex, age):
            self.name = name
            self.sex = sex
            self.age = age
    
    class Teacher(People):
        def __init__(self, name, sex, age, title): #派生
            self.name = name
            self.sex = sex
            self.age = age
            self.title = title
        def teach(self):
            print('%s is teaching'%self.name)
    
    obj = Teacher('lili','female', 28, '高级教师') #只会找自己类中的__init__
    print(obj.name, obj.sex, obj.age, obj.title)  #lili female 28 高级教师

    这里Teacher中的__init__内的前三行又是在写重复代码,若想在子类派生出的方法重用父类的功能,可以用两种方式:

    # #方式一‘:指名道姓’地调用某一个类的函数
    # class Teacher(People):
    #     def __init__(self, name, sex, age, title):
    #         People.__init__(self, name, age, sex)
    #         self.title = title
    #     def teach(self):
    #         print('%s is teaching' %self.name)
    # obj = Teacher('lili','female', 28, '高级教师') #只会找自己类中的__init__
    #
    # print(obj.teach())  #lili is teaching
    #                     #None
    
    # #方法二:super()
    '''
    调用super()会得到一个特殊的对象,该对象专门用来引用父类的属性,且严格按照
    MRO规定的顺序向后查找
    '''
    class Teacher(People):
        def __init__(self, name, sex, age, title):
            super().__init__(name, age, sex) #调用的是绑定方法,自动传入self
            self.title = title
        def teach(self):
            print('%s is teaching' %self.name)
    
    obj = Teacher('lili','female', 28, '高级教师') #只会找自己类中的__init__
    
    print(obj.teach())  #lili is teaching
                        #None

    注意:在python2中super 的使用需要完整地写成super(自己的类名,self),而在python3中可以简写为super()。

    -新式类:
    1.凡是继承object的类或子孙类都是新式类
    2.在python3中所有的类都默认继承object
    -经典类:
    1.在python2中才会有经典类与新式类之分
    2.在python2中,凡是没有继承object的类,都是经典类

    class User(object):
        pass
    
    class User:
        x =10
        pass
    
    class Sub(User):
        pass
    
    print(User.__dict__)      #  {'__module__': '__main__', 'x': 10, '__dict__':
                                # <attribute '__dict__' of 'User' objects>,
    print(object)   #<class 'object'>

    调用mro 返回的是一个继承序列

      super 的继承顺序严格遵循mro继承序列

    class Father1:
        x =10
        pass
    
    class Father2:
        x = 20
        pass
    #多继承的情况下,从左到右
    class Sub(Father1,Father2):
        def __init__(self):   #注意__int__不是__init__
            print(super().__delattr__)
    
    print(Sub.mro())   # [<class '__main__.Sub'>, <class '__main__.Father1'>, <class '__main__.Father2'>, <class 'object'>]
    obj = Sub()
    print(object)   #<class 'object'>

    在python3中提供了一种查找新式类查找顺序的内置方法

      mro():会把当前类的继承关系列出来

    注:supper()会严格按照mro列表的顺序往后查找

    class A:        #默认继承object
        def test(self):
            print('from A.test')
            super().test()
    class B:
        def test(self):
            print('from B.test')
    class C(A, B):
        pass
    c = C()
    #检查super的继承顺序
    #mro(): 会把当前类的继承关系列出来。
    print(C.mro()) #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
    c.test()    #from A.test
                #from B.test

    砖石继承:

      多继承情况下造成’“砖石继承”

      mro 的查找顺序:

        -新式类:

          -广度优先

        -经典类:

          -深度优先

    #新式类
    class A(object):
        def test(self):
            print('from A')
        pass
    
    class B(A):
        def test(self):
            print('from B')
        pass
    
    class C(A):
        def test(self):
            print('from C')
        pass
    class D(B):
        def test(self):
            print('from D')
        pass
    
    class E(C):
        def test(self):
            print('from E')
        pass
    
    class F(D, E):
        def test(self):
            print('from F')
        pass
    # F-->D-->B-->E-->C-->A-->object,注意:当class C(A)中A不存在时,则查找顺序为F-D-B-A-E-C->object
    print(F.mro())
    obj = F()
    obj.test()
    如果是经典类,查找顺序为:
    F-D-C-A-E-C
  • 相关阅读:
    Orcad Pspice仿真
    AD导入Allegro brd文件(导入后找不到PCB的解决方法)
    VJTAG转VME DTB
    win10 非Unicode应用程序显示设置
    MFC多文档视图编程总结
    VC MFC开发示例下载
    FPGA仿真及时序约束分析
    VMWARE Thin APP
    VPX技术基础概论
    SecureCRT脚本(VBS)运行
  • 原文地址:https://www.cnblogs.com/xy-han/p/11938195.html
Copyright © 2011-2022 走看看