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.__bases__)
    print(Sub.x)

    如何寻找继承关系

    -确认谁是子类

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

      -小猪佩奇对象 --->猪子类 --->动物父类

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

    -再确认谁是父类

      -动物类就是父类

      -得先抽象,再继承

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

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

    问题:代码冗余
    #老师类
    class OldTeacher:
        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}正在修改分数...')
    #学生类
    calss OldboyStudent:
        school = 'oldboy'
        country = 'China'
        
        def__init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.age = sex
        #学生选择课程
        def choose_course(self)
            print(f'学生{self.name}正在选择课程...')
    stu1 = OldboyStudent('XXX',18,'male')
    print(stu1.school,stu1.name,stu1.age,stu1.sex)
    
    tea1 = OldboyTeacher('sean',18,'male')
    print(tea1.school,tea1.name,tea1.age,tea1.sex)
    
    #解决代码冗余问题
    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('XXX',18,'male')
    print(stu1.school,stu1.name,stu1.age,stu1.sex)
    tea1 = OldboyTeacher('sean',18,'male')
    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()
    #foo_obj.x = 1000   #对象添加属性的操作,并不是修改子类的属性
    print(foo_obj.x)
    print('对象的名称空间:',foo_obj.__dict__)
    print('子类的名称空间: ',Foo.__dict__)
    print('父类的名称空间: ',Goo.__dict__)

    派生

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

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

    #父类
    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...

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

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

    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
                self.sal = sal
            
             def change_score(self):
             print(f'老师 {self.name} 修改分数...')
             
    class OldboyStudent(OldboyPeople):
    
        def __init__(self, name, age, sex, girl):
            self.name = name
            self.age = age
            self.sex = sex
            self.girl = girl
    
        def choose_course(self):
            print(f'学生 {self.name} 选择课程...')
    
    
    tea1 = OldboyTeacher('tank', 17, 'male', 15000000)
    stu1 = OldboyStudent('XXX', 28, 'male', '凤姐')
    print(tea1.name, tea1.age, tea1.sex, tea1.sal)
    print(stu1.name, stu1.age, stu1.sex, stu1.girl)
    
    '''
    解决问题: 子类重用父类的属性,并派生出新的属性。
        两种方式:
            1.直接引用父类的__init__为其传参,并添加子类的属性。
            2.通过super来指向父类的属性。
                - super()是一个特殊的类,调用super得到一个对象,该对象指向父类的名称空间。
                
            注意: 使用哪一种都可以,但不能两种方式混合使用。
    '''
    #方式一:
    class OldboyPeople:
        school = 'oldboy'
    
        def __init__(self, name, age, sex):  # self == tea1, name == 'tank', age == 17, sex == 'male'
            self.name = name
            self.age = age
            self.sex = sex
    
    
    class OldboyTeacher(OldboyPeople):
    
        # tea1, 'tank', 17, 'male', 15000000
        def __init__(self, name, age, sex, sal):
            # self.name = name
            # self.age = age
            # self.sex = sex
            # 类调用类内部的__init__,只是一个普通函数
            # OldboyPeople.__init__(tea1, 'tank', 17, 'male')
            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('XXX', 28, 'male', '凤姐')
    print(stu1.name, stu1.age, stu1.sex, stu1.girl)
    
    # 方式二:
    class OldboyPeople:
        school = 'oldboy'
    
        # self == tea1
        def __init__(self, name, age, sex):  # self == tea1, name == 'tank', age == 17, sex == 'male'
            self.name = name
            self.age = age
            self.sex = sex
    
    
    class OldboyTeacher(OldboyPeople):
    
        # tea1, 'tank', 17, 'male', 15000000
        def __init__(self, name, age, sex, sal):
            # super() ---> 特殊的对象 ---> 对象.属性 ---> 父类的名称空间
            # 会将调用类传入的对象当做第一个参数传给__init__()
            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('XXX', 28, 'male', '凤姐')
    print(stu1.name, stu1.age, stu1.sex, stu1.girl)

    -新式类:

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

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

    -经典类:

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

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

    class User(object):
        pass
    
    class User:  # (<class 'object'>,)
        x = 10
        pass
    
    
    class Sub(User):
        pass
    
    
    print(User.__dict__)
    
    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()

     

     

  • 相关阅读:
    .NET开发者必备的工具箱
    LINQ标准查询操作符详解(转)
    转)SSO单点登录在互联网电商应用中的解决方案(基于CAS的改造)
    构建高并发高可用的电商平台架构实践(转)
    使用UI Automation实现自动化测试 --微软提供的控件Pattern
    使用UI Automation实现自动化测试 --工具使用
    [archlinux][daily] 自建DNS服务器 / 建立本地DNS cache / 使用dnsmasq加速上网
    [skill] 补码
    nfs的时间问题,影响编译
    [daily][CentOS][SELinux]用key免登陆不成功,原来是SElinux在搞事情
  • 原文地址:https://www.cnblogs.com/lvguchujiu/p/11937787.html
Copyright © 2011-2022 走看看