• 继承、派生、新式类与经典类


    继承

    Downwards is the only way forwards .——《盗梦空间》

    面向对象阶段最重要的知识点:继承、封装、多态

    1.什么是继承?

    指新建类的方法,新建的类称之为子类或者派生类,子类继承的类叫做父类,也称之为基类或者超类。
    继承特征:
    子类可以继承父类的属性(特征与技能),并且可以派生出自己的属性(特征与技能)。
    在python中一个子类可以继承多个父类,其他语言一个子类只可以继承一个父类

    2.为什么要继承?

    继承的目的是为了减少代码的冗余(减少重复代码)

    3.如何实现继承?

    1.首先要确定好谁是子类谁是父类.
    2.在定义类时子类+(),()内写父类,实现继承.

    class 父类:
         pass
    
    class 子类(父类):
         pass
    #父类
    class ParentClass1:
        pass
    
    class ParentClass2:
        pass
    #子类
    class Subclass1(ParentClass1):
        pass
    
    class Subclass2(ParentClass1,ParentClass2):
        pass
    
    print(Subclass2.__bases__)
    #(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
    #查看继承的父类:__bases__,是类的属性,用来查找自己的父类,通过元组的形式返回所继承的父类
    
    

    寻找继承关系

    如何寻找继承关系?
    要想寻找继承关系,首先抽象再继承。
    ——先抽象(抽象思想):

    奥巴马——》人类——》动物类
    麦兜——》猪类——》动物类
    小丁丁——》狗类——》动物类
    抽象定义动物类,父类。
    特征:眼睛、鼻子...
    技能:
    吃喝...

    ——再继承(在程序中)

    继承的关系:
    对象:特征与技能的结合体
    类:一系列特征与技能的结合体
    继承:一系列类相同的特征与技能的结合体

    class SchoolPeople:
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
    class Students(SchoolPeople):
        def choose_course(self):
            print(f'{self.name} is choosing course.')
    
    class Teachers(SchoolPeople):
        def teach(self):
            print(f'{self.name} is teaching students.')
    
    stu1 = Students('xiaoming','15','男')
    stu1.choose_course()
    

    xiaoming is choosing course.

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

    对象查找属性先从自己的名称空间查找,若当前类是子类,并且没有该属性,就去父类中查找,如果父类也没有就报错__class__查看当前对象的类。
    注意:对象查找属性不管父类有没有这个属性,只要子类有就不会去父类中查找

    查看对象名称空间
    print(tea1._dict__)
    查看对象的属性,查看当前对象的类__class
    _

    查看子类名称空间
    print(tea1._class__.__dict__)
    查看父类名称空间
    print(tea1.__class__.__bases__[0].__dict
    _)#查看第一个父类的名称空间

    #验证对象属性的查找顺序
    class Foo:
        def f1(self):
            print('Foo.f1')
    
        def f2(self):
            print('Foo.f2')
            self.f1()
    
    class Soo(Foo):
        def f1(self):
            print('Soo.f1')
    
    soo_obj = Soo()
    soo_obj.f2()
    '''
    Foo.f2
    Soo.f1
    '''
    

    派生

    什么是派生?

    派生指子类继承父类的属性,并且派生自己的属性。
    如果子类和父类都有这个属性,以子类自己的属性为准。
    继承指的是类与类的关系,子类与父类是从属关系。

    子类派生出新的属性,并重用父类的属性

    class SchoolPeople:
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
    class Teacher(SchoolPeople):
        def __init__(self,name,age,gender,level,sal):
            SchoolPeople.__init__(self,name,age,gender)#重用父类的属性
            self.level = level#派生出的属性
            self.sal = sal#派生出的属性
    
    tech1 = Teacher('xiaohua','17','男','10','5w')
    print(tech1.level)
    

    重用父类属性的两种方式

    方式一:

    直接通过父类.(调用)__init__,把__init__当做普通函数使用,传入对象与继承的属性,如上例中的重用。
    方式二:

    super是一个特殊的类,在子类中调用super()会得到一个特殊的对象,通过“.”
    指向父类的名称空间。

    class SchoolPeople:
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
    class Teacher(SchoolPeople):
        def __init__(self,name,age,gender,level,sal):
            super().__init__(name,age,gender)#重用父类的属性(注意括号里面没有self)
            self.level = level#派生出的属性
            self.sal = sal#派生出的属性
    

    注意:两种方式不要混着使用

    新式类与经典类

    新式类与经典类(了解)(面试会问)

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

    python3中都是新式类,继承object类的都是新式类,py3中默认继承object类。

    钻石继承(菱形继承)

    关于mro()

    mro():是object——》type的函数,用来查看多继承情况下,当前类的继承顺序, .mro()方法其实就是在查找mro()方法
    一个子类如果继承多个父类,属性的查找顺序是从左向右依次查找,最后找object

    钻石继承

    钻石继承(菱形继承):钻石继承就是一个子类有多个父类,每个父类又有多个不同的父类......这些父类的祖先最终是同一个祖宗。(面试问)

    在多继承情况下可能会出现钻石继承的情况。

    钻石继承下对象属性的查找顺序

    --经典类——》深度优先:从左向右查找,一条分支找到底,若果没找到就去另一条分支继续找。

    ——新式类——》广度优先:从左向右查找,和经典类的区别是最后找所有分支共同的父类

    验证查找顺序代码

    class A(object):
        def test(self):
            print('from A')
    
    class B(A):
        def test(self):
            print('from B')
    
    class C(A):
        def test(self):
            print('from C')
    
    class D(B):
        def test(self):
            print('from D')
    
    class E(C):
        def test(self):
            print('from E')
    
    class F(D,E):
        # def test(self):
        #     print('from F')
        pass
    f1=F()
    f1.test()
    print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
    
    #新式类继承顺序:F->D->B->E->C->A
    #经典类继承顺序:F->D->B->A->E->C
    #python3中统一都是新式类
    #pyhon2中才分新式类与经典类
    

    通过继承实现修改json模块数据类型

    通过继承实现为json增加数据类型:

    import json
    from datetime import date ,datetime
    print(json.JSONDecoder)#<class 'json.decoder.JSONDecoder'>
    print(datetime.today())#当前时间
    print(date.today())#当前日期
    #从开发者的角度考虑,可以将json不支持的数据类型转成json支持的是数据类型
    #如:
    '''dict1 = {
        'name':'tank',
        'today':str(datetime.today()),
        'today1':str(date.today())
    }
    res = json.dumps(dict1)
    print(res)
    #{"name": "tank", "today": "2019-10-10 14:30:26.967368", "today1": "2019-10-10"}
    从开源者的角度考虑,Python time strftime() 函数接收以时间元组,并返回以可读字符串表示的当地时间,
            格式由参数format决定。'''
    class MyJson(json.JSONEncoder):
        def default(self,o):
            if isinstance(o,datetime):#判断o是否是datetime的一个实例对象
                return o.strftime('%Y-%m-%d %X')
    
            elif isinstance(o,date):
                return o.strftime('%Y-%m-%d')
            else:
                return super().default(self,o)#在json中也有default这个方法
    
    dict1 = {
        'name':'tank',
        'today':datetime.today(),
        'today1':date.today()
    }
    res = json.dumps(dict1,cls = MyJson)#cls=None,默认指向的是原json的JSONEncoder,加上之后优先使用外面的类
    print(res)
    

    总结

    1.什么是继承?
    继承指的是新建类的方法, 新建的类称之为子类或者派生类,子类继承的类叫做父类,也称之为基类或超类.

    继承的特征:
      	子类可以继承父类的属性(特征与技能), 并且可以派生出自己的属性(特征与技能).
    

    2.继承的目的:
    继承的目的是为了减少代码冗余(减少重复代码).

    3.什么是抽象?
    抽象指的是抽取相似的部分,称之为抽象.

    4.继承的关系:
    对象是特征与技能的结合体.
    类是一系列对象相同的特征与技能的结合体.
    继承是一系列类相同的特征与技能的结合体.

    5.在继承背景下,对象属性的查找顺序:
    1.对象查找属性会先从对象的名称空间中查找.
    2.若对象没有,则会去类里面找.
    3.若当前类是子类,并且没有对象找的属性,会去父类中查找

    6.什么是派生?
    派生指的是子类继承父类的属性,并且派生出新的属性.(*****)
    子类派生出新的属性,若与父类的属性相同,则以子类的为准.
    继承是谁与谁的关系, 指的是类与类的关系,子类与父类是从属关系.

    7.子类派生出新的属性,并重用父类的属性:
    - 直接通过 父类.(调用)init,把__init__当做普通函数使用,传入对象与继承的属性.
    - super是一个特殊的类,在子类中调用super()会得到一个特殊的对象,

    8.什么经典类与新式类:
    继承object的类都称之为新式类.
    在python2中,凡是没有继承object的类都是经典类.

    9.在多继承的情况下形成的钻石继承 (继承顺序)
    - 经典类:
    深度优先
    - 新式类:
    广度优先

  • 相关阅读:
    洛谷P1129 [ZJOI2007] 矩阵游戏(二分图最大匹配)
    牛客NC51316 Going Home (二分图最大权匹配)
    洛谷P2055 [ZJOI2009]假期的宿舍(二分图最大匹配)
    Codeforces Round #702 (Div. 3) 全部七题
    Educational Codeforces Round 104 (Rated for Div. 2) A~D
    Leetcode 567. 字符串的排列(滑动窗口)
    基于macOS Catalina 10.15.7下GitHub Pages + Hexo 5.3.0 + 阿里云的博客部署
    关于两个数的LCM
    2021牛客寒假算法基础集训营1 补题 ABCEFIJ
    macOS上运行jupyter notebook程序:服务似乎挂掉了,但是会立刻重启 报错OMP: Error #15: Initializing libomp.dylib, but found libiomp5.dylib already initialize
  • 原文地址:https://www.cnblogs.com/ghylpb/p/11648032.html
Copyright © 2020-2023  润新知