• 面向对象特性之 继承


    面向对象三大特性

    继承

    封装

    多态

    继承

    一、什么是继承

    继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。父类的属性和方法,子类中也有。

    格式就是子类名加括号,括号内是父类名:

    class A:
        pass
    
    class B(A):  # B就继承了A
        pass
    

    这里提一下新式类和经典类的区别

    新式类:只要继承了object类,就是新式类,在python3中,默认都是新式类

    ​ 在python2中,需要显示指定继承object才是新式类

    经典类:在python2中,没有继承object的类,就是经典类

    ​ python3中没有经典类

    二、类的继承分为单继承和多继承

    class A(object):
        pass
    class B(A):
        pass
    #  B继承了A这个类,单继承
    
    class C(A,B):
        pass
    # C继承了A和B,多继承
    
    

    类的其他内置属性:__名字__

    print(B.__dict__) # 类的属性和方法
    
    print(B.__name__) # 类名
    
    print(B.__bases__) # 类的父类
    
    

    继承中属性的查找顺序:

    先在对象中找---》子类中找---》父类中找(多继承父类的话,从左到右,先从第一个父类找)---》父类中找不到就报错

    三、利用继承减少代码冗余

    # 这里首先利用面向对象写一个老师和学生的类,他们的基类都是人
    # 这里不用继承
    class Person:
        school = 'oldboy'
    
    class Teacher(Person):
        def __init__(self,name,age,level):
            self.name=name
            self.age=age
            self.level=level
    
    class Student(Person):
        def __init__(self,name,age,course):
            self.name=name
            self.age=age
            self.course=course
    # 以上代码老师和学生的类都有共同属性:name和age,那就可以把这两个属性放到人的类中,然后老师和学生的类来继承人的类
    
    class Person(object):
        school = 'oldboy'
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    class Teacher(Person):
        pass
    
    class Student(Person):
        pass
    
    # 这样就减少了代码的冗余
    
    
    
    

    注意:子类实例化会自动调用__init__方法,如果子类中没有,会去父类中找,父类中有几个参数就要传几个参数

    四、多层继承和多继承

    # 多层继承:一层一层的继承下去
    class A:
        a="AAAA"
        
    class B(A):
        a="BBB"
    
    class C(B):
        a="CCC"
        pass
    
    class D(C):
        a = "DDD"
        pass
    
    
    # 多继承 
    class A:
        a="AAAA"
        
    class B:
        a="BBB"
    
    class C:
        a="CCC"
        pass
    
    class D(A,B,C):   # 类 D 继承了上面多个类
        a = "DDD"
        pass
    
    
    # 多继承的多层
    class A:
        a="AAAA"
        
    class B(A):
        a="BBB"
    
    class C(B):
        a="CCC"
        pass
    
    class D(A,B,C):
        a = "DDD"
        pass
    
    

    五、继承属性查找顺序

    5.1 菱形问题

    继承的菱形问题(显示的都继承一个类,不是object类):新式类和经典类的查找顺序是不一样的。

    新式类(py3中全是新式类):广度优先---从左侧开始,一直往上找,找到菱形的顶点结束(不包括菱形顶点),继续下一个继承的父类往上找,找到菱形的顶点结束(不包括菱形顶点),最后找到菱形顶点。

    经典类(只有py2中才有):深度优先---从左侧开始,一直往上找,找到菱形的顶点结束(包括菱形顶点)继续下一个继承的父类往上找,找到菱形的顶点结束(不包含菱形定点)。

    不出现菱形问题:正常查找

    #继承的菱形问题:新式类和经典类的查找顺序是不一样的
    #新式类的查找属性:广度优先
    #经典类:深度优先
    
    class G(object):
        a = "GGG"
        pass
    class F(G):
        # a = "FFF"
        pass
    class E(G):
        # a = "EEE"
        pass
    class D(G):
        # a = "DDD"
        pass
    class C(F):
        # a="CCC"
        pass
    class B(E):
        # a="BBB"
        pass
    class A(B,C,D):
        # a="AAAA"
        pass
    
    a=A()
    print(a.a)
    

    以上代码就出现新式类的菱形问题,查找顺序就是广度优先:

    img

    经典类的菱形问题,查找顺序就是深度优先:

    img

    5.2 根据mro列表查找

    mro列表,继承顺序查找列表(只在新式类中有)

    print(A.mro())
    print(A.__mro__)
    #  两种方式都可以
    

    六、继承重用父类方法得两种方式

    6.1 方式一:指名道姓的使用,跟继承关系无关

    # 父类中object写与不写,在py3中没有区别,
    # 有的人在py3中这么写,为了向下兼容
    # 调用父类方法的第一种方式 :指名道姓的方式,跟继承关系无关
    class Person(object):
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
    def init_1(self,name,age):
        self.name=name
        self.age=age
    
    class Student:
        school = 'yyyy'
        
        def __init__(self,name,age,course):
            Person.__init__(self,name,age)    #指名道姓的使用Person的__init__方法,Preson中有三个参数就必须传三个
            init_1(self,name,age)
            self.course=course
    
    stu=Student('nick',19,'python')
    print(stu.name)
    

    6.2 方式二:通过super关键字,跟继承关系有关

    class Person(object):
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
    class Student(Person):
        school = 'yyyy'
        def __init__(self,name,age,course):
            #super()相当于得到了一个特殊对象,第一个参数不需要传,调用绑定方法,会把自己传过去
            ##########    self不需要传,不需要传
            super().__init__(name,age)
            #看到别人这么写:super(类名,对象)  在py3中为了兼容py2
            #在py3中这么写和省略写法完全一样
            #在py2中必须super(Student,self)写
            # super(Student,self).__init__(name,age)
            self.course=course
    
    stu=Student('nick',19,'python')
    print(stu.name)
    print(stu.age)
    print(stu.course)
    
    

    6.3 总结

    有继承关系的时候,通常用super关键字方法;

    指名道姓的方法在以下情况下用:

    • 没有继承关系
    • 如果继承了多个父类,super是按照mro列表找,现在想指名道姓的用某个父类的某个方法,就需要指名道姓的使用
  • 相关阅读:
    坐标系统和投影的来龙去脉原创
    ArcEngine这本书怎么样
    如何构建达芬奇的DSP Server【转】
    ccs编译问题
    linux下环境变量设置[转]
    普通人的编辑利器——Vim 【转】
    关闭linux防火墙
    GT_Trace的使用[z]
    davinciDM6446 LINUX环境配置
    TI DaVinci(达芬奇)入门
  • 原文地址:https://www.cnblogs.com/zhuangyl23/p/11420981.html
Copyright © 2020-2023  润新知