继承
1.什么是继承?
继承指的是新建类的方法, 新建的类称之为子类或者派生类, 子类继承的类叫做父类,也称之为基类或超类.
继承的特征:
子类可以继承父类的属性(特征与技能), 并且可以派生出自己的属性(特征与技能).
注意: 在python中,一个子类可以继承多个父类,其他语言只能一个子类继承一个父类.
2.为什么要继承?
继承的目的是为了减少代码冗余(减少重复代码).
3.如何实现继承?
1.首先要确定好谁是子类,谁是父类.
2.在定义类时, 子类 + (), ()内写父类,实现继承.
3.查看继承的父类: __bases__,是类的属性,用来查找当前类的父类.(多个的话,用元组的形式打印出来)
# 父类
class ParentClass1:
pass
class ParentClass2:
pass
# 子类
class SubClass1(ParentClass1):
pass
# 继承多个父类
class SubClass2(ParentClass1, ParentClass2):
pass
# 查看继承的父类: __bases__,是类的属性,用来查找当前类的父类.
print(SubClass1.__bases__) # (<class '__main__.ParentClass1'>,)
print(SubClass2.__bases__) # (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
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)
继承背景下对象属性的查找顺序
1.对象查找属性会先从对象的名称空间中查找.
2.若对象没有,则会去类里面找.
3.若当前类是子类,并且没有对象找的属性,会去父类中查找
注意: 对象查找属性,若子类有,不管父类有没有,以子类的为准.
class Foo:
def f1(self):
print('Foo.f1')
def f2(self):
print('Foo.f2')
self.f1()
class Soo(Foo):
def f1(self):
print('Soo.f1')
soo_obj = Soo()
soo_obj.f2()
'''
Foo.f2
Soo.f1
'''
派生
派生指的是子类继承父类的属性,并且派生出新的属性.(*****)
子类派生出新的属性,若与父类的属性相同,则以子类的为准.
继承是谁与谁的关系, 指的是类与类的关系,子类与父类是从属关系.
class Foo:
def f1(self):
print('Foo.f1')
def f2(self):
print('Foo.f2')
self.f1()
class Soo(Foo):
def f1(self):
print('Soo.f1')
soo_obj = Soo()
soo_obj.f1() # Soo.f1
子类派生出新的属性,并重用父类属性
解决方式有两种:
方式一:
直接通过 父类.(调用)__init__,把__init__当做普通函数使用,传入对象与继承的属性.
方式二:
super是一个特殊的类,在子类中调用super()会得到一个特殊的对象,
通过"."指向的是父类的名称空间.
注意: 两种方式不要混合使用.
方式一: class OldboyPeople: 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, 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}')
方式二:
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}')
新式类与经典类
在python2中,才会有新式类与经典类之分.
在python3中,所有的类都是新式类.
新式类:
继承object的类都称之为新式类.
python3中,子类不继承自定义的类,默认继承object.
经典类:
在python2中,凡是没有继承object的类都是经典类.
mro(): 属于object--> type的函数, 用来查看当前类的继承顺序, 在多继承的情况下
class A: # x = 2 pass class B: # x = 3 pass # 多继承情况下: class C(A, B): # print('C...') # x = 1 pass # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>] print(object) print(C.mro())
<class 'object'>
[<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 # 新式类: F-D-B-E-C-A-object f1 = F() f1.test() # 经典类: F-D-B-A-E-C
通过继承实现json模块数据类型
json无法把date,datetime序列化
可以添加数据类型
方法一:开发者角度,直接转成str
import json
from datetime import date, datetime
#开发者的角度: 直接转成str
dict1 = {
'name': 'tank',
'today': str(datetime.today()),
'today2': str(date.today())
}
res = json.dumps(dict1)
print(res)
方法二:开源者的角度: 修改json源码
isinstance:
python内置的函数,可以传两个参数,判断参数一是否是参数二的一个实例.
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)