zoukankan      html  css  js  c++  java
  • Python3 类的继承

    继承的基本概念

    什么是继承

    继承指的是一种新建类的方法, 新建的类称之为子类或者派生类

    子类继承的类叫做父类, 也称之为基类或者超类

    • 类的特征: 子类可以继承父类的属性(特征和技能), 并且可以派生出自己的属性(特征和技能)
    • 在Python中, 一个子类可以继承多个父类(多继承)

    继承有什么用

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

    如何实现继承

    在定义类时候, 通过class 子类(父类):实现继承

    初识继承

    下面我们就通过代码来实现继承

    # 父类
    class ParentClass1:
        pass
    
    
    # 父类
    class ParentClass2:
        pass
    
    
    # 子类 单继承
    class ChildClass1(ParentClass1):
        pass
    
    
    # 子类 多继承
    class ChildClass2(ParentClass1, ParentClass2):
        pass
    

    我们可以通过__bases__方法来查看当前类继承的父类

    # 查看当前类的父类
    print(ChildClass1.__bases__)  # (<class '__main__.ParentClass1'>,)
    
    print(ChildClass2.__bases__)  # (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
    

    寻找继承关系

    如何寻找继承关系

    • 先抽象, 再继承
    • 关系梳理:
      1. 对象是特征和技能的结合体
      2. 类是一系列对象相同特征和技能的结合体
      3. 父类是一系列子类相同的特征和技能的结合体

    实例演示

    # 父类
    class PyMan:
        language = 'Python'
    
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
    
    
    # 老师类
    class PyTeacher(PyMan):
        def teach_python(self):
            print(f'老师[{self.name}]在教Python...')
    
    
    # 学生类
    class PyStudent(PyMan):
        def learn_python(self):
            print(f'学生[{self.name}]在学Python...')
    
    
    teacher = PyTeacher('龟叔', 18, 'female')
    student = PyStudent('MrBigB', 17, 'male')
    
    print(teacher.name, teacher.age, teacher.gender)  # 龟叔 18 female
    print(student.name, student.age, student.gender)  # MrBigB 17 male
    
    teacher.teach_python()  # 老师[龟叔]在教Python...
    student.learn_python()  # 学生[MrBigB]在学Python...
    
    

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

    • 在继承背景下, 对象的属性查找顺序:

      1. 先从对象的名称空间中查找
      2. 若对象没有, 会从子类中查找
      3. 若子类中没有, 则回去父类中查找

      ​ 注意: 对象-->子类-->父类, 找到既停止寻找

    class ParentClass:
        def f1(self):
            print('from ParentClass.f1')
    
        def f2(self):
            print('from ParentClass.f2')
    
    
    class ChildClass(ParentClass):
        def f1(self):
            print('from ChildClass.f1')
    
    
    obj = ChildClass()
    
    obj.f1()  # from ChildClass.f1
    obj.f2()  # from ParentClass.f2
    

    派生

    • 什么是派生: 指的是子类在继承了父类的属性基础上, 又拥有了自己的一些属性, 这些属性就是派生出来的

    • 子类会覆盖父类的属性, 子类和父类是从属关系

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

      对于上面老师和学生的例子, 如果我们要给老师增加薪资属性, 学生增加班级班级属性

      super().__init__() 等同于Pyman.__init__()

    class PyMan:
        language = 'Python'
    
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
    
    
    # 老师类
    class PyTeacher(PyMan):
        def __init__(self, name, age, gender, salary):
            super().__init__(self, name, age, gender)
            self.salary = salary
    
        def teach_python(self):
            print(f'老师[{self.name}]在教Python...')
    
    
    # 学生类
    class PyStudent(PyMan):
        def __init__(self, name, age, gender, class_no):
            super().__init__(self, name, age, gender)
            self.class_no = class_no
            
        def learn_python(self):
            print(f'学生[{self.name}]在学Python...')
    

    新式类和经典类

    • 在Python2中, 才会有新式类和经典类之分
    • 在Python3中, 所有类都是新式类
    • 新式类: 继承object的类都是新式类. 在Python3中, 没有继承自定义类的, 默认继承object. 父类是新式类, 则子类也是新式类, 因此Python3中所有的类都是新式类
    • 经典类: 在Python2中, 凡是没有继承object的类都是经典类
    # Python3
    class A(object):
        pass
    
    
    class B:
        pass
    
    
    print(A.__bases__)  # (<class 'object'>,)
    print(B.__bases__)  # (<class 'object'>,)
    
    # Python2
    class A(object):
        pass
    
    
    class B:
        pass
    
    
    print A.__bases__  # (<class 'object'>,)
    print B.__bases__  # ()
    
    

    钻石继承

    • 砖石继承也被称为菱形继承, 是在多继承情况下的形成的
    • 砖石继承的继承顺序:
      1. 经典类: 深度优先
      2. 新式类: 广度优先

    我们也可以通过子类.mro()方法查看方法解析顺序

    class G:
        pass
    
    
    class E(G):
        pass
    
    
    class B(E):
        pass
    
    
    class F(G):
        pass
    
    
    class C(F):
        pass
    
    
    class D(G):
        pass
    
    
    class A(B, C, D):
        pass
    
    
    print(A.mro())
    
    '''
    [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>]
    '''
    

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

    # 增加date和datetime两种数据类型
    
    import json
    from datetime import date, datetime
    
    
    dict = {
        'language': 'Python',
        'date': date.today(),
        'time': datetime.today()
    }
    
    class MyJson(json.JSONEncoder):
        def default(self, o):
    
            if isinstance(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)
    
    
    res = json.dumps(dict, cls=MyJson)  #  # cls=None,默认指向的是原json的JSONEncoder
    
    print(res)  
    # {"language": "Python", "date": "2019-10-10", "time": "2019-10-10 18:13:39"}
    
    
    
  • 相关阅读:
    如何在一个项目中同时包含mvc建站、webapi接口
    解决api、WebService跨域问题
    mvc接口、webapi、webservice 对比
    云服务器 远程mysql 无法连接
    c#快速写本地日志
    使用筛选器特性标记方法解决webapi 跨域问题
    流量控制(滑动窗口协议)
    解释Windows7“上帝模式”的原理
    Linux网络协议栈(二)——套接字缓存(socket buffer)
    理解MySQL——架构与概念
  • 原文地址:https://www.cnblogs.com/bigb/p/11649773.html
Copyright © 2011-2022 走看看