• 面向对象三大特性1-继承


    面向对象的三大特性之继承

    一、什么是继承?

    继承:是一种新建类的方式,新建的类称之为子类或者派生类,子类继承的类叫做父类,也可以称之为基类或者超类。

    继承的特征

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

    class Parent:
        
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class Son(Parent):
        
        def choose_course(self, course):
            print(f'学生[{self.name}]选择课程[{course}]')
    

    注意:在Python中,一个子类可以继承多个父类,其他语言只能一个子类继承一个父类。

    class Parent1:
        pass
    
    
    class Parent2:
        pass
    
    
    class Sub1(Parent1, Parent2):
        pass
    

    二、为什么要继承?

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

    三、如何实现继承?

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

    四、查看继承的父类

    # 可以用__bases__,这是类的属性,用来查找当前类的父类.
    
    print(Son.__bases__)  # (<class '__main__.Parent'>,)
    print(Sub1.__bases__)  # (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
    
    

    五、继承与抽象

    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} 修改分数...]')
    
    # 学生类:  名字,年龄,性别
    class OldboyStudent(OldboyPeople):
    
        # 学生可以选择课程
        def choose_course(self, course):
            print(f'学生[{self.name}]选择课程[{course}]')
    
    stu1 = OldboyStudent('小丁丁', 95, 'female')
    tea1 = OldboyTeacher('tank', 17, 'male')
    
    print(stu1.name, stu1.age, stu1.sex)
    print(tea1.name, tea1.age, tea1.sex)
    
    
    # 小丁丁 95 female
    # tank 17 male
    

    六、继承后对象属性查找顺序

    对象名称空间 -->子类名称空间 --> 父类名称空间

    # 父类
    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} 修改分数...]')
    
    
    tea1 = OldboyTeacher('tank', 17, 'male')
    print(tea1.school)
    
    # 查看对象名称空间
    print(tea1.__dict__)
    
    # __class__: 对象的属性,查看当前对象的类.
    
    # 查看子类名称空间
    print(tea1.__class__.__dict__)
    # 查看父类名称空间
    print(tea1.__class__.__bases__[0].__dict__)
    
    '''
    oldboy
    
    {'name': 'tank', 'age': 17, 'sex': 'male'}
    
    {'__module__': '__main__', 'change_score': <function OldboyTeacher.change_score at 0x00000122CCFECDC8>, '__doc__':None}
    
    {'__module__': '__main__', 'school': 'oldboy', '__init__':<function OldboyPeople.__init__ at 0x00000122CCFE6B88>,'__dict__': <attribute '__dict__' of'OldboyPeople' objects>, '__weakref__': <attribute'__weakref__' of 'OldboyPeople' objects>, '__doc__': None}
    '''
    

    七、派生

    1、什么是派生

    派生指的是子类继承父类的属性,并且新增新的属性。

    子类派生出的新属性,若与父类的属性名相同,则以子类的为准。

    继承是谁与谁的关系,指的是类与类的关系,子类与父类是从属关系。

    2、派生子类更新父类属性

    2.1 方法一:调用父类init

    直接调用 父类.__init__(),把__init__当做普通函数使用,传入对象与继承的属性。

    class OldboyTeacher(OldboyPeople):
        # 等级, 薪资
        def __init__(self, name, age, sex, level, sal):
            OldboyPeople.__init__(self, name, age, sex)
            self.level = level
            self.sal = sal
    
    
    class OldboyStudent(OldboyPeople):
        # 课程
        def __init__(self, name, age, sex, course):
            OldboyPeople.__init__(self, name, age, sex)
            self.course = course
    
        def choose_course(self):
            print(f'学生{self.name}选择课程{self.course}')
            
    tea1 = OldboyTeacher('tank', 17, 'male', 9, '3.0')
    stu1 = OldboyStudent('小健健', 20, 'female', 'python')
    print(tea1.name, tea1.level)
    print(stu1.name, stu1.course)
    stu1.choose_course()
    
    '''
    tank 9
    小健健 python
    学生小健健选择课程python
    '''
    

    2.2 方法二:super

    super():

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

    class OldboyTeacher(OldboyPeople):
        # 等级, 薪资
        def __init__(self, name, age, sex, level, sal):
            super().__init__(name, age, sex)
            self.level = level
            self.sal = sal
    
    
    class OldboyStudent(OldboyPeople):
        # 课程
        def __init__(self, name, age, sex, course):
            super().__init__(name, age, sex)
            self.course = course
    
        def choose_course(self):
            print(f'学生{self.name}选择课程{self.course}')
             
    tea1 = OldboyTeacher('tank', 17, 'male', 9, '3.0')
    stu1 = OldboyStudent('小健健', 20, 'female', 'python')
    print(tea1.name, tea1.level)
    print(stu1.name, stu1.course)
    stu1.choose_course() 
    
    '''
    tank 9
    小健健 python
    学生小健健选择课程python
    '''
    

    八、新式类和经典类(了解)

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

    在python3中,所有的类都是新式类.

    1、新式类

    继承object的类都称之为新式类.python3中,子类不继承自定义的类,默认继承object.

    2、经典类

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

    3、mro函数

    mro():

    属于object--> type的函数。

    在多继承的情况下 , 用来查看当前类的继承顺序.

    class A:
        pass
    class B:
        pass
    # 多继承情况下:
    class C(A, B):  
        pass
    
    print(C.mro())
    
    # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
    

    九、钻石继承(了解)

    钻石继承也可以称之为菱形继承

    • 在多继承的情况下形成的钻石继承的继承顺序:
      • 经典类:深度优先
      • 新式类:广度优先
    # 验证
    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 - E-C-A -object
    # 经典类: F- D-B-A - E-C
    

    十、通过继承修改json模块的数据类型

    import json
    from datetime import date, datetime
    
    print(json.JSONEncoder)
    print(datetime.today())  # 当前时间
    print(date.today())  # 当前日期
    
    # 开源者的角度: 修改json源码
    class MyJson(json.JSONEncoder):
        def default(self, o):
    
            # 子类派生的功能
            # 判断o是否式datetime的一个实例
            if isinstance(o, datetime):
                return o.strftime('%Y-%m-%d %X')
            elif isinstance(o, date):
                return o.strftime('%Y-%m-%d')
            else:
                # 继承父类的default方法的功能
                return super().default(self, o)
    
    
    dict1 = {
        'name': 'tank',
        'today': datetime.today(),
        'today2': date.today()
    }
    
    res = json.dumps(dict1, cls=MyJson)  # cls=None,默认指向的是原json的JSONEncoder
    print(res)
    
    
    
    '''
    <class 'json.encoder.JSONEncoder'>
    2019-10-10 16:26:11.875435
    2019-10-10
    {"name": "tank", "today": "2019-10-10 16:26:11", "today2": "2019-10-10"}
    '''
    
  • 相关阅读:
    vue双向数据绑定原理解析及js代码实现
    react 实现tab切换
    vue不是内部或外部命令,解决办法
    JavaScript 基础知识 表达式和运算符
    JavaScript 基础知识 变量与数据类型
    Animation动画-小动画
    Ajax的封装
    esp32 python上位机(命令行)
    ESP32扫描环境中的所有WiFi并且通过串口选择需要连接的WiFi
    Linux修改开机图形/etc/motd
  • 原文地址:https://www.cnblogs.com/bowendown/p/11650690.html
Copyright © 2020-2023  润新知