zoukankan      html  css  js  c++  java
  • python-面向对象之继承

    一、继承介绍

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

    python中继承的特点:

      1.子类可以遗传/重用父类的属性

      2.子类可以有多个父类

      3.Python中的继承类分为新式类和经典类

        新式类:继承了object的类,以及他的子类都是新式类

        经典类:没有继承object的类,以及他的子类都是经典类

        在Python3中,没有显示的声明,默认继承object类,所有的类都是新式类

        在Python2中才区分新式类和经典类,没有显示继承任何类,也不会继承object类。

    使用继承的好处:减少类与类之间的代码冗余

    二、继承的定义

    在子类中加括号,括号里加上父类

    class parent1:
        x=111
    
    class sub1(parent1):
        pass

    调用属性,查看父类:

    class parent1:
        x=111
    
    class parent2:
        x=222
    
    class sub1(parent1):
        pass
    
    class sub2(parent1,parent2):
        pass
    
    print(parent1.__bases__)#查看父类 (<class 'object'>,)
    print(sub1.__bases__)#(<class '__main__.parent1'>,)
    print(sub2.__bases__)#(<class '__main__.parent1'>, <class '__main__.parent2'>)
    obj = sub1()
    print(obj.x)#111

    三、利用继承解决类与类之间的代码冗余问题

    可以将类与类之间的重复代码定义在一个父类中,思考的时候从下往上思考统计

    class OldboyPeople:
        school = 'Oldboy'
    
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class OldboyStudent(OldboyPeople):
    
        def choose_course(self):
            print('%s choosing course' % self.name)
    
    class OldboyTeacher(OldboyPeople):
    
        def score(self,stu,num):
            stu.score=num
    
    
    stu1=OldboyStudent('刘二蛋',38,'male')
    print(stu1.__dict__)
    
    tea1=OldboyTeacher('egon',18,'male')
    print(tea1.__dict__)

    不过这个时候,不同的类要是想用自己独有的属性应该怎么办呢?

    在子类派生的新方法中重用父类的功能 方式一:

    指名道姓地引用一个类中的函数

    class OldboyPeople:
        school = 'Oldboy'
    
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class OldboyStudent(OldboyPeople):
        def __init__(self, name, age, sex, score=0):
            OldboyPeople.__init__(self,name,age,sex)
            self.score = score
    
        def choose_course(self):
            print('%s choosing course' % self.name)
    
    class OldboyTeacher(OldboyPeople):
        def __init__(self,name,age,sex,level):
            OldboyPeople.__init__(self,name,age,sex)
            self.level=level
    
        def score(self,stu,num):
            stu.score=num
    
    
    stu1=OldboyStudent('刘二蛋',38,'male')
    print(stu1.__dict__)
    
    tea1=OldboyTeacher('egon',18,'male',10)
    print(tea1.__dict__)

    总结:

      1.与继承无关

      2.访问的是类的函数,没有自动传值的效果

    在学习子类派生方法中重用父类的功能第二个方式之前先来说一下在继承背景下的属性查找

    1.单继承状态下的属性查找:

    class Foo:
        xxx=444
        pass
    class Bar1(Foo):
        # xxx=333
        pass
    
    class Bar2(Bar1):
        # xxx=222
        pass
    obj=Bar2()
    # obj.xxx=111
    
    print(obj.xxx)#444

    单继承查找的优先级别:对象->对象的类->父类->object

    2.多继承状态下的属性查找:

    如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性

    class G:
        x = 'G'
        pass
    
    # 第三层
    class E(G):
        # x = 'E'
        pass
    
    class F:
        # x = 'F'
        pass
    
    # 第二层
    class B(E):
        # x = 'B'
        pass
    
    class C(F):
        # x = 'C'
        pass
    
    class D:
        # x = 'D'
        pass
    
    # 第一层
    class A(B, C, D):
        # x = 'A'
        pass
    
    obj = A()
    # obj.x = 111
    print(obj.x)
    View Code

    此时属性的查找顺序优先级是:对象->对象的类->按照从左到右的顺序一个分支一个分支的找下去

    菱形继承:属性的查找方式有两种,深度优先和广度优先

      新式类:广度优先查找,从左往右一个分支一个分支的查找,在找到最后一个分支采才去查找顶级类

      经典类:深度优先查找,从左往右一个分支一个分支的查找,在第一个分支就查找到顶级类

    继承原理:

      对于定义的每一个类,Python会计算出一个方法解析顺序(MRO)列表,这个列表就是一个简单的所有基类的线性顺序表

    # 第四层:
    class G(object):
        # x = 'G'
        pass
    
    # 第三层
    class E(G):
        # x = 'E'
        pass
    
    class F(G):
        # x = 'F'
        pass
    
    # 第二层
    class B(E):
        # x = 'B'
        pass
    
    class C(F):
        # x = 'C'
        pass
    
    class D(G):
        # x = 'D'
        pass
    
    # 第一层
    class A(B, C, D):
        # x = 'A'
        pass
    
    
    obj=A()
    View Code
    [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>]

    注:今天威老师讲了一个很好记的方式,就是先深度查找,然后去除前面重复的,留下的就是查找属性的顺序。

    在子类派生的新方法中重用父类的功能 方式二:

    super()必须在类中使用

    在Python2中:super(自己的类名,自己的对象)

    在Python3中:super()

    调用该函数会得到一个特殊的对象,该对象专门用来访问父类中的属性,(完全参照mro列表)

    总结:

      1.严格依赖继承的mro列表

      2.访问的是绑定方法,有自动传值的效果

    class OldboyPeople:
        school = 'Oldboy'
    
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class OldboyStudent(OldboyPeople):
        def __init__(self, name, age, sex, score=0):
            super(OldboyStudent,self).__init__(name,age,sex)
            self.score = score
    
        def choose_course(self):
            print('%s choosing course' % self.name)
    
    class OldboyTeacher(OldboyPeople):
        def __init__(self,name,age,sex,level):
            super().__init__(name,age,sex)
            self.level=level
    
        def score(self,stu,num):
            stu.score=num
    
    
    stu1=OldboyStudent('刘二蛋',38,'male')
    print(stu1.__dict__)
    
    tea1=OldboyTeacher('egon',18,'male',10)
    print(tea1.__dict__)
    View Code

    还是需要加油学习!

  • 相关阅读:
    python命令方式和关键字
    python注释及语句分类
    基于物联网的智能垃圾桶设计
    基于51单片机的交通灯控制设计
    python安装以及版本检测
    python简介
    关于deepin系统安装design compiler的问题解答
    关于安装deepin+window10双系统有时没有声音的问题
    如何使用notepad运行python程序
    15 一个完整的链式队列代码
  • 原文地址:https://www.cnblogs.com/mangM/p/9508401.html
Copyright © 2011-2022 走看看