zoukankan      html  css  js  c++  java
  • 继承

    继承

    1.什么是继承?

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

    在python中,一个子类可以继承多个父类(面试题)

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

    2.继承的作用?

    减少代码的冗余

    3.如何实现继承?

    1)先确认呢谁是子类,谁是父类

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

    父类
    class Father1:
        pass
    class Father2:
        pass
    class Father3:
        pass
    子类
    class Sub(Father1,Father2,Father3):
        pass
    
    # 子类。__bases__查看父亲
    print(Sub.__bases__)
    print(Sub.x)
    

    4.如何寻找继承关系:

    确认谁是子类

    确认谁是父类

    先抽象,再继承:

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

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

    代码冗余
    # 老师类
    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}正在选择课程。。。')
            
    解决代码冗余
    # 老男孩人类
    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}正在选择课程...')
            
    
        
    

    程序的执行顺序是由上而下,父类必须定义在子类的上方

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

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

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

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

    ps: 对象中添加属性的操作
        坑:并不是修改子类的属性
    

    派生:

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

    ​ 若子类中的方法名与父类的相同有先用子类的

    # 父类
    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...
    
    # 派生后继承关系查找验证:
    bar_obj = Bar()
    bar_obj.f2()
    
    
    结果:
    from Foo.f2...
    from Bar.f1..
    
    

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

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

    代码冗余
    # 老师类
    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}正在选择课程。。。')
    

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

    ​ 两种方式:

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

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

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

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

    第一种
    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 __init__(self, name, age, sex, sal):
            # 类调用内部的__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, hobby):
            OldboyPeople.__init__(self, name, age, sex)
            self.hobby = hobby
    
        def choose_course(self):
            print(f'学生{self.name}进行选课!')
    
    
    teacher = OldboyTeacher('tank', 28, 'female', 120000)
    print(teacher.name, teacher.sex, teacher.age, teacher.sal)
    
        
    
    第二种
    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 __init__(self, name, age, sex, sal):
            # 类调用内部的__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, hobby):
            super().__init__(name, age, sex)
            self.hobby = hobby
    
        def choose_course(self):
            print(f'学生{self.name}进行选课!')
    
    
    teacher = OldboyTeacher('tank', 28, 'female', 120000)
    print(teacher.name, teacher.sex, teacher.age, teacher.sal)
    

    经典类与新式类:

    ​ 新式类:

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

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

    ​ 经典类:

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

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

    # class User(object):
    #     pass
    python3中所有的类都是继承object
    
    class User:
        x = 10
        pass
    
    
    class Sub(User):
        pass
    
    
    print(User.__dict__)
    
    
    {'__module__': '__main__', 'x': 10, '__dict__': <attribute '__dict__' of 'User' objects>, '__weakref__': <attribute '__weakref__' of 'User' objects>, '__doc__': None}
    
    
    python2中
    #!/usr/bin/u/ubv/a python
    # _*_ coding:utf8 _*_
    
    
    class User(object):
        x = 10
        pass
    
    
    class Sub(User):
        pass
    
    
    print(User.__dict__)
    
    {'__dict__': <attribute '__dict__' of 'User' objects>, 'x': 10, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'User' objects>, '__doc__': None}
    
    
    #!/usr/bin/u/ubv/a python
    # _*_ coding:utf8 _*_
    
    
    class User():
        x = 10
        pass
    
    
    class Sub(User):
        pass
    
    
    {'x': 10, '__module__': '__main__', '__doc__': None}
    
    

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

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

    多继承的情况下:从左至右

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

    class A:
        def test(self):
            print('from A.test')
            super().test()
    
    
    class B:
        def test(self):
            print('from B.test')
    
    
    class C(A, B):
        pass
    
    print(C.mro())
    
    [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
    
    c = C()
    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
    print(F.mro())
    obj = F()
    obj.test()
    
    
    [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    from F
    
    菱形继承下的经典类和新式类的详解:
    https://blog.csdn.net/XiaoMaGe1996/article/details/80828864
    
  • 相关阅读:
    Apache Log4j 学习笔记
    关于BindingResult
    Java源码分析:深入探讨Iterator模式
    hibernate的ID生成策略(annotation方式@GeneratedValue)
    HTML5本地存储不完全指南
    pageX,clientX,offsetX,layerX的那些事
    getHibernateTemplate().execute(new HibernateCallback())方法
    jQuery.extend 与 jQuery.fn.extend 的区别
    16个优秀的JavaScript教程和工具推荐
    Spring 2.5:Spring MVC中的新特性
  • 原文地址:https://www.cnblogs.com/godlover/p/11937791.html
Copyright © 2011-2022 走看看