zoukankan      html  css  js  c++  java
  • 继承

    继承

    什么是继承?(What)

    • 继承指的是新建类的方法,新建的类称之为子类或派生类,子类继承的类叫做父类,也称之为基类或超类
    • 继承的特征:子类可以继承父类的属性(特征与技能),并且可以派生出自己的属性(特征与技能)

    为什么要继承?(What)

    • 较少代码冗余

    如何实现继承(How)

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

    查看继承的父类

    class ParentClass1:
        pass
    
    class ParentClass2:
        pass
    
    class SubClass1(ParentClass1):
        pass
    
    print(SubClass1.__bases__)	# __bases__ 是类的属性,用来查找当前类的父类
    
    class SubClass2(ParentClass1,ParentClass2):	#在python中一个子类可以继承多个父类
        pass
    
    print(SubClass2.__bases__)
    
    # __bases__ 是类的属性,用来查找当前类的父类
    #在python中一个子类可以继承多个父类---python中独有,其他语言一个子类只继承一个父类,面试会问
    '''
    (<class '__main__.ParentClass1'>,)
    (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
    '''
    

    寻找继承关系

    如何寻找继承关系

    • 先抽象,再继承

    什么是抽象

    • 抽取相似的部分
      • 奥巴马-->人类-->动物类
      • 麦兜-->猪类-->动物类
      • 小丁丁-->狗类-->动物类
    • 抽象定义动物类,称之为父类
      • 特征:
        • 眼睛,鼻子,...
      • 技能
        • 吃,喝...
    • 继承
      • 奥巴马对象<--调用人类<--继承动物类
      • 麦兜对象<--调用猪类<--继承动物类
      • 小丁丁对象<--调用狗类<--继承动物类

    继承关系

    • 对象是特征与技能的结合体
    • 类是一系列对象中相同的特征与技能的结合体
    • 继承是一系类中相同的特征与技能的结合体

    在继承关系下对象属性的查找顺序

    1. 先从对象名称空间查找
    2. 没有再从对象所属子类查找
    3. ,没有最后从父类中查找

    在某一层找到就不会继续寻找

    # 父类
    class OldboyPeople:
        school = 'oldboy'
    
        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} 修改分数...]')
    
    
    teacher = OldboyTeacher('tank', 17, 'male')
    
    print(teacher.__class__)    #查看对象所属的类
    print(teacher.__class__.__dict__)   #查看对象所属类的名称空间
    
    print(teacher.__class__.__bases__)  #查看对象所属的类的父类
    print(teacher.__class__.__bases__[0].__dict__)  #查看对象所属的类的第一个父类的名称空间
    
    print(id(teacher.school))
    print(id(OldboyPeople.school))
    '''
    <class '__main__.OldboyTeacher'>
    
    {'__module__': '__main__', 'change_score': <function OldboyTeacher.change_score at 0x00000185B7F9EB70>, '__doc__': None}
    
    (<class '__main__.OldboyPeople'>,)
    
    {'__module__': '__main__', 'school': 'oldboy', '__init__': <function OldboyPeople.__init__ at 0x00000185B7F9EAE8>, '__dict__': <attribute '__dict__' of 'OldboyPeople' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyPeople' objects>, '__doc__': None}
    
    2219246848072
    2219246848072
    '''
    

    派生

    • 派生指的是子类继承父类的属性并且派生出新的属性
    • 子类派生出新的属性,若与父类的属性相同,则以子类为准
    • 继承指的是子类与父类之间的从属关系

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

    方式一

    #通过 父类.__init__ ,把 __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,level,salary):
            OldboyPeople.__init__(self,name,age,sex)
            self.level = level
            self.salary = salary
    
    teacher = OldboyTeacher('tank',18,'male',9,'3.0w')
    print(teacher.__dict__)
    
    '''
    {'name': 'tank', 'age': 18, 'sex': 'male', 'level': 9, 'salary': '3.0w'}
    '''
    

    方式二

    #super是一个特殊的类,在子类中调用super()会得到一个特殊的对象,该对象通过 "." 指向父类的名称空间
    
    # 父类
    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,level,salary):
            super().__init__(name,age,sex)
            self.level = level
            self.salary = salary
    
    teacher = OldboyTeacher('tank',18,'male',9,'3.0w')
    print(teacher.__dict__)
    
    '''
    {'name': 'tank', 'age': 18, 'sex': 'male', 'level': 9, 'salary': '3.0w'}
    '''
    

    super类的使用方法---super(type,object)与super()

    super(type,object)

    #super(type,object),type作用是定义在__mro__数组中的那个位置开始找,obj定义的是用哪个类的__mro__元素
    
    class A(object):
        def fun(self):
            print('A.fun')
    
    class B(object):
        def fun(self):
            print('B.fun')
    
    class C(object):
        def fun(self):
            print('C.fun')
    
    class D(A,B):
        def fun(self):
            print('D.fun')
    
    class E(B, C):
        def fun(self):
            print('E.fun')
    
    class F(D, E):
        def fun(self):
            print('F.fun')
    
    print(F.mro())
    print(B.mro())
    super(B , B()).fun()	#会报错
    
    '''
    AttributeError: 'super' object has no attribute 'fun'
    
    [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.A'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]
    
    [<class '__main__.B'>, <class 'object'>]
    '''
    

    super

    super()事实上是懒人版的super(type , obj),这种方式只能用在类体内部,Python会自动把两个参数填充上,type指代当前类,obj指导当前类的实例对象,相当于super(class , self)

    新式类与经典类

    在python2中,才会有新式类与经典类之分,在python3中,所有类都是新式类---面试会问

    新式类

    • 继承object的类都称之为新式类
    • python3中所有的类默认继承object
    class Foo(object):
        pass
    
    print(Foo.__bases__)
    
    class Foo:
        pass
    
    print(Foo.__bases__)
    
    '''
    (<class 'object'>,)
    (<class 'object'>,)
    '''
    

    经典类

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

    #python2
    '''
    >>> class Foo(object):
    ...     pass
    ...
    >>> Foo.__bases__
    (<type 'object'>,)
    >>> class Foo:
    ...     pass
    ...
    >>> Foo.__bases__
    ()
    '''
    

    mro()---Method Resolution Order (方法解析顺序)-->属于object-->属于type

    python内置的函数用来查看在多继承情况下,当前类的继承顺序

    class A:
        x = 'A'
        pass
    
    class B:
        x = 'B'
        pass
    
    class C(A,B):
        pass
    
    print(C.x)
    print(C.__mro__)
    print(C.mro())
    
    '''
    A
    (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
    [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
    '''
    

    菱形继承

    在多继承的情况下形成(继承顺序)

    • 经典类
      • 深度优先
    • 新式类
      • 广度优先

    验证

    # python2
    class A:
        # 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
    
    f1 = F()
    f1.test()
    
    #经典类(深度优先): F-->D-->B-->A-->E-->C
    #新式类(广度优先): F-->D-->B-->E-->C-->A
    

    通过继承机制修改json数据格式

    import json
    from datetime import date,datetime
    
    print(date.today())
    print(datetime.today())
    print(type(date.today()))
    print(type(datetime.today()))
    print('*'*100)
    
    dic = {'name':'蔡启龙','date':date.today(),'today':datetime.today()}
    # print(json.dumps(dic))  #TypeError: Object of type 'date' is not JSON serializable
    
    #开发者角度:直接转成str
    
    #开源者角度:修改源码
    #isinstance:python,可以穿两个参数,判断参数一是否是参数二的一个实例
    
    a = date(2019,10,11)
    print(type(a))
    b = a.strftime('%Y-%m-%d %X')
    print(b)
    print(type(b))
    print('*'*100)
    
    class MyJson(json.JSONEncoder):
        def default(self, o):
            if isinstance(o,type(date.today())):
                return o.strftime('%Y-%m-%d %X')
            if isinstance(o,type(datetime.today())):
                return o.strftime('%Y-%m-%d %X')
    
            #继承父类的default方法的功能
            return super().default(o)
    
    res = json.dumps(dic,cls=MyJson)
    print(res)
    print('*'*100)
    
    print(json.loads(res))
    
    '''
    2019-10-11
    2019-10-11 00:20:52.540284
    <class 'datetime.date'>
    <class 'datetime.datetime'>
    ****************************************************************************************************
    <class 'datetime.date'>
    2019-10-11 00:00:00
    <class 'str'>
    ****************************************************************************************************
    {"name": "u8521u542fu9f99", "date": "2019-10-11 00:00:00", "today": "2019-10-11 00:20:52"}
    ****************************************************************************************************
    {'name': '蔡启龙', 'date': '2019-10-11 00:00:00', 'today': '2019-10-11 00:20:52'}
    '''
    
  • 相关阅读:
    GridView与ArrayAdapter的结合
    翻翻git之---闪烁动画的TextView RevealTextView
    希捷硬盘扩容软件-----DiscWizard
    项目管理的酸甜苦辣
    【转】Bootloader之uBoot简介(转)
    【转】uboot移植(一)BootLoader基本概念
    【转】U-boot分析与移植(1)----bootloader分析
    【转】MIPS交叉编译环境的建立
    【转】RTSP实例解析
    【转】Eclipse快捷键 10个最有用的快捷键----不错
  • 原文地址:https://www.cnblogs.com/-406454833/p/11651513.html
Copyright © 2011-2022 走看看