目录
继承的基本概念
什么是继承
继承指的是一种新建类的方法, 新建的类称之为子类或者派生类
子类继承的类叫做父类, 也称之为基类或者超类
- 类的特征: 子类可以继承父类的属性(特征和技能), 并且可以派生出自己的属性(特征和技能)
- 在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'>)
寻找继承关系
如何寻找继承关系
- 先抽象, 再继承
- 关系梳理:
- 对象是特征和技能的结合体
- 类是一系列对象相同特征和技能的结合体
- 父类是一系列子类相同的特征和技能的结合体
实例演示
# 父类 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...
继承背景下的对象属性查找顺序
在继承背景下, 对象的属性查找顺序:
- 先从对象的名称空间中查找
- 若对象没有, 会从子类中查找
- 若子类中没有, 则回去父类中查找
注意:
对象-->子类-->父类
, 找到既停止寻找
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__ # ()
钻石继承
- 砖石继承也被称为菱形继承, 是在多继承情况下的形成的
- 砖石继承的继承顺序:
- 经典类: 深度优先
- 新式类: 广度优先
我们也可以通过子类.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"}