继承的含义
面向对象中继承是用来描述类与类之间数据的从属关系,通过继承可以减少代码冗余,提升开发效率,同样也支持多继承
基本使用
class A: # 被继承的类称为父类或者基类name = 'from A'class B(A): # 继承别人的类称为子类或者派生类passprint(B.name)# from A"""在python中一个类可以同时继承多个父类"""class A:nameA = 'from A'class B:nameB = 'from B'class C:nameC = 'from C'class MyClass(A, B, C):passprint(MyClass.nameA)# from Aprint(MyClass.nameB)# from Bprint(MyClass.nameC)# from C
继承的本质
class Person: # 多个类相同数据和功能的结合体,父类def __init__(self, name, age, gender):self.name = nameself.age = ageself.gender = genderclass Teacher(Person): # 多个对象相同数据和功能的结合体,子类def teach(self):print(f'{self.name}老师正在讲课')class Student(Person): # 多个对象相同数据和功能的结合体,子类def study(self):print(f'{self.name}正在在学习')obj_1 = Student('kevin', 22, 'male') # 数据与功能的结合体,对象obj_1.study()# kevin正在在学习
继承的分类
python2存在经典类与新式类
- 经典类:在 python2.2 之前⼀直使⽤的是经典类,经典类在基类的根什么都不写
- 新式类: 在 python2.2 之后出现了新式类,新式类的特点是基类的根,
object类
class A:passclass B(object):passprint(A.__base__)# 空的print(B.__base__)# <class 'object'>
python3只有新式类
- 新式类:python3中使⽤的都是新式类,如果基类谁都不继承,那这个类会默认继承 object
# 有时候我们在定义类的时候会习惯性的写class MyClass(object):pass# 为了兼容python2和python3
名字的查找顺序(继承)
核心:先从对象自己的名称空间中查找,没有择取产生对象的类中查找,如果还没有并且类有父类则去父类中查找,以此往复下去
对象 >>> 类 >>> 父类
记住一点,名字的查找顺序永远都是,先从当前对象自身开始查找
单继承
class A:def func_1(self):print('from A.func_1')def func_2(self):print('from A.func_2')class MyClass(A):def func_1(self):print('from MyClass.func_3')obj = MyClass()obj.func_1() # 先找自己,在找继承# from MyClass.func_3obj.func_2() # 自己没有,在找继承# from A.func_2
class A:name = 'from A'class B(A):name = 'from B'class C(B):name = 'from C'class MyClass(C):name = 'from MyClass' # 有则找MyClass里面的nameobj = MyClass()obj.name = '我自己的name'print(obj.name) # 先找自己,在找调用的类,类里没有,在找父类一直往上推# 我自己的name

多继承
普通多继承
class A:# name = 'a'passclass B:name = 'b'class C:name = 'c'class MyClass(A,B,C):# name = 'MyClass'passobj = Myclass()print(obj.name)# b
非菱形多继承
父类中名字的查找顺序按照继承时从左往右依次查找,如果多个父类还有分类,那么遵循”深度优先”
class E:name = 'from E'class F:# name = 'from F'passclass D:# name = 'from D'passclass A(D):# name = 'from A'passclass B(E):# name = 'from B'passclass C(F):# name = 'from C'passclass MyClass(A,B,C):# name = 'from MyClass'passobj = MyClass()# obj.name = 'from obj'print(obj.name)

菱形多继承
父类中名字的查找顺序就是按照继承时从左往右依次查找,如果多个父类还有分类 那么遵循”广度优先”
class M:name = 'from M'class E(M):name = 'from E'passclass F(M):name = 'from F'passclass D(M):# name = 'from D'passclass A(D):# name = 'from A'passclass B(E):name = 'from B'passclass C(F):# name = 'from C'passclass MyClass(A,B,C):# name = 'from MyClass'passobj = MyClass()print(obj.name)# from B

派生类用法(子类)
在写的子类需要使用父类的方法,并且还需要基于该方法做扩展,这样的子类称为派生类(本质还是子类),使用关键字super关键字来实现
class Person:def __init__(self, name, age, gender):self.name = nameself.age = ageself.gender = genderclass Teacher(Person):def __init__(self, name, age, gender, salary, hobby):# 用了Person类里面的__init__方法# super(Teacher,self).__init__(name, age, gender) # 子类调用父类的完整语法super().__init__(name, age, gender) # 子类调用# 自己还要添加一个额外的东西self.salary = salaryself.salary = hobbyclass Student(Person):def __init__(self, name, age, gender, stu_id, class_id):# 用了Person类里面的__init__方法super().__init__(name, age, gender)# 自己还要添加一个额外的东西self.stu_id = stu_idself.class_id = class_idobj_1 = Teacher('kevin', 22, 'male', 1000, 'run')obj_2 = Student('kevin', 22, 'male', 123, 123)print(obj_1.__dict__)# {'name': 'kevin', 'age': 22, 'gender': 'male', 'salary': 'run'}print(obj_2.__dict__)# {'name': 'kevin', 'age': 22, 'gender': 'male', 'stu_id': 123, 'class_id': 123}
派生功能前瞻
class MyClass(list):def append(self, args):if args == 123:print("数字123不能追加")returnsuper(MyClass, self).append(args)print(f"{self}")obj = MyClass()obj.append(111)# [111]obj.append(222)# [111, 222]obj.append(123)# 数字123不能追加obj.append(333)# [111, 222, 333]
派生实际应用
前言
json不能序列化python所有的数据类型,只能是一些基本数据类型,通过继承的方式将,研究并重写json序列化方法
import datetimeimport jsontimes = datetime.date.today()print(type(times))# <class 'datetime.date'>json.dumps(times)# TypeError: Object of type 'date' is not JSON serializable
研究
研究函数dumps参数中有一个叫cls,如果这个参数为None则等于JSONEncoder ,查看后发现JSONEncoder是一个类,类里有一个方法叫default,正是报错的原因


实现
写一个类去继承JSONEncoder,然后重新default方法
import datetimeimport jsonclass MyJsonEncoder(json.JSONEncoder):def default(self, o):if isinstance(o, datetime.datetime):return o.strftime('%Y-%m-%d %X')elif isinstance(o, datetime.date):return o.strftime('%Y-%m-%d')return super().default(o) # 调用父类的default(让父类的default方法继续执行,防止有其他额外操作)d = {'t1': datetime.datetime.today(), 't2': datetime.date.today()}res = json.dumps(d, cls=MyJsonEncoder) # 指定cls执行为我们写的类print(res)# {"t1": "2022-04-09 17:33:36", "t2": "2022-04-09"}
