• day21--继承--派生


    继承:

    什么是继承?

    ​ 继承是一种新建类的方式,新建的类称之为字类或派生类,继承的父类称之为基类或超类。

    ​ 在python中,一个子类可以继承多个父类。

    ​ 在其他语言中,一个子类只能继承一个父类。

    继承的作用:

    ​ 解决代码的冗余。

    如何实现继承?

    ​ 1.先确认谁是子类,谁是父类。

    ​ 2.在定义类子类时,子类名(父类名)。

    # 父类
    class Father1:
        x = 1
        pass
    
    class Father2:
        pass
    
    #子类
    class Sub(Father1, Father2):
        pass
    #子类.__bases__查看父类
    print(Sub.__bases__)
    print(Sub.x)
    

    如何寻找继承关系:

    ​ 1.确认谁是子类

    ​ 2.确认谁是父类

    ​ -- 抽取对象之间相似的部分总结出类。

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

    #代码冗余:
    #老师类
    class OldboyTeacher:
        school = 'oldboy'
        country = 'China'
    
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def change_score(self):
            print(f'老师{self.name}正在修改分数...')
    
    #学生类
    class OldboyStudent:
        school = 'oldboy'
        country = 'China'
    
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
            #学生选课程
        def choose_course(self):
            print(f'学生{self.name}正在选择课程...')
    
    #学生类
    stu1 = OldboyStudent('AA', 19, 'female')
    print(stu1.school, stu1.name, stu1.age, stu1.sex) #oldboy AA 19 female
    
    #老师
    tea1 = OldboyTeacher('tank', 18, 'male')
    print(tea1.school, tea1.name, tea1.age, tea1.sex) # oldboy tank 18 male
    
    # 解决代码冗余问题
    #老男孩人类
    class OldboyPeople:  #我们经过分析可以得到上面学生类和老师类共同拥有						的特征,我们定义老男孩人类的父类。
        school = 'oldboy'
        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('AA', 39, 'female')
    print(stu1.school, stu1.name, stu1.age, stu1.sex)#oldboy AA 39 female
    tea1 = OldboyTeacher('大脸', 75, 'female')
    print(tea1.school, tea1.name, tea1.age, tea1.sex)#oldboy 大脸 75 female
    
    

    继承背景下对象属性的查找顺序

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

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

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

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

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

    派生

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

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

    #父类:
    class Foo:
        def f1(self):
            print('from Foo.f1...')
    
        def f2(self):
            print('from Foo.f2...')
            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...
    
    bar_obj = Bar()
    bar_obj.f2() #from Foo.f2...
                    #from Bar.f1...  #因为子类和父类中的方法名一样,优先使用子类名,
    
    

    子类继承父类并重用父类的属性与方法

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

    问题: 子类重写父类的_ _ init _ _ 导致代码更加冗余

    解决问题:子类重用父类的属性,并派生出新的属性
    --两种方式:
    --1.直接引用父类的_ _ init _ _为其传参,并添加子类的属性。
    --2.通过super来指向父类的属性。
    --super()是一个特殊的类,调用super得到一个对象,该对象指向父类的名称空间。

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

    #解决方法
    #方式一
    class OldboyPeople:
        school = 'oldboy'
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class OldboyTeacher(OldboyPeople):
    
        def __init__(self, name, age, sex, sal):
            # self.name = name
            # self.age = age
            # self.sex = sex
            # #类调用类内部的__init__,值时一个普通函数
            OldboyPeople.__init__(self, name, age, sex)
            self.sal = sal
    
        def change_score(self):
            print(f'老师{self.name}修改分数...')
    
    class OldboyStudent(OldboyPeople):
    
        def __init__(self, name, age, sex, girl):
            OldboyPeople.__init__(self, name, age, sex)
            self.girl = girl
        def choose_course(self):
            print(f'学生{self.name}选择课程...')
    
    tea1 = OldboyTeacher('tank', 17, 'male', 15000000)
    print(tea1.name, tea1.age, tea1.sex, tea1.sal)
    
    stu1 = OldboyStudent('姚玉鑫', 28, 'male', '凤姐')
    print(stu1.name, stu1.age, stu1.sex, stu1.girl)
    
    #方法二
    class OldboyPeople:
        school = 'oldboy'
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class OldboyTeacher(OldboyPeople):
        def __init__(self, name, age, sex, sal):
            super().__init__(name, age, sex)
            self.sal = sal
    
        def change_score(self):
            print(f'老师{self.name}修改分数...')
    
    class OldboyStudent(OldboyPeople):
        def __init__(self, name, age, sex, girl):
            super().__init__(name, age, sex)
            self.girl = girl
    
        def choose_course(self):
            print(f'学生{self.name}选择课程...')
    
    tea1 = OldboyTeacher('tank', 17, 'male', 15000000)
    print(tea1.name, tea1.age, tea1.sex, tea1.sal)
    
    
    stu1 = OldboyStudent('姚玉鑫', 28, 'male', '凤姐')
    print(stu1.name, stu1.age, stu1.sex, stu1.girl)
    
    经典类与新式类(了解)
    • 新式类:

      ​ --1.凡是继承object的类或子孙类都是新式类。

      ​ --2.在python3中所有的类都默认继承object。

    • 经典类:

      --1.在python2中才会有经典类与新式类之分。

      --2.在python2中,凡是没有继承object的类,都是经典类。

    supre严格遵循mro继承顺序

    调用mro返回的是一个继承序列: (了解知识点)

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

    在python3中提供了一个查找新式类查找顺序的内置方法. mro(): 会把当前类的继承关系列出来。

    class Father1:
        x = 10
        pass
    class Father2:
        x = 20
        pass
    #多继承的情路况下:从左到右
    class Sub(Father1, Father2):
        def __init__(self):
            print(super().__delattr__)
    
    print(Sub.mro())
    obj = Sub()
    print(object)
    

    多继承情况下造成 “钻石继承”

    ​ 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
    # print(F.mro())
    obj = F()
    obj.test()
    
  • 相关阅读:
    SpringCloud(四)GateWay网关
    C++中的间接宏函数
    一个C++引用库的头文件预编译陷阱
    谈谈C++中的数据对齐
    在C++中实现aligned_malloc
    WPF中的DesignerProperties
    在.NET 6中使用DateOnly和TimeOnly
    在 Ubuntu 上安装 .NET SDK 或 .NET 运行时
    Microsoft Build 2021第二天
    Microsoft Build 2021大会开始后,Develop Blog一系列更新
  • 原文地址:https://www.cnblogs.com/lishuangjian/p/11938302.html
Copyright © 2020-2023  润新知