一、继承
类的继承
- 面向对象三要素之一,继承Inheritance
- class Cat(Animal)这种形式就是从父类继承,继承可以让子类从父类获取特征(属性和方法)
在面向对象的世界中,从父类继承,就可以直接拥有父类的属性和方法,这样可以减少代码,多复用,子类可以定义自己的属性和方法
1、查看继承的特殊属性和方法
- base : 类的基类
- based : 类的基类元组
- mro : 显示方法查找顺序,基类的元组
- __mro()__方法 : 显示方法查找顺序,基类的元组
subclasses() : 类的子类列表
2、继承中的查找顺序
- 从父类继承,自己没有的就可以到父类中找
- 私有的都是不可以访问的,但是本质上依然是改了名称放在这个属性所在类的_dict-中
- 继承时,公有的,子类和实例都可以随意访问,私有成员被隐藏了,子类和实例不可直接访问
- 当私有变量所在的类内的方法中可以访问这个私有变量
- 属性查找属性:实例的dict--》类的dict--》父类dict
二、派生
派生:子类定义自己新的属性,如果与父类同名,以子类自己的为准
在子类派生出的新方法中重用父类的功能:
方式一:指名道姓地调用(与继承没有什么关系)
方式二:super()调用(严格依赖于继承)
super ( ) 的返回值是一个特殊的对象,该对象专门用来调用父类中的属性,super()会严格按照mro列表从当前查找到的位置继续往后查找
经典类和新式类:
1、新式类: 继承object的类,以及该类的子类,都是新式类
在python3中,如果一个类没有指定继承的父类,默认就继承object,所以说python3中所有的类都是新式类
2、经典类(只有在python2才区分经典类与新式类):没有继承object的类,以及该类的子类,都是经典类
在多继承背景下的属性查找:
属性查找
obj.x
1、先从obj.__dict__
2、对象的类.__dict__
3、父类.__dict__
如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性
如果继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先
print(F.__mro__) # F.mro() #只有新式类才有这个属性可以查看线性列表,查看属性查找顺序,经典类没有这个属性
菱形继承问题
在Python中子类可以同时继承多个父类,如A(B,C,D)
- 如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这条分支,最后找D这条分支的顺序直到找到我们想要的属性
- 如果继承关系为菱形结构,即子类的父类最后继承了同一个类,那么属性的查找方式有两种
经典类(了解)
一条路走到黑,深度优先
查找顺序:A -> B -> E -> G -> C -> F -> D
新式类
不找到各类最后继承的同一个类,直接去找下一个父类,广度优先
查找顺序:A -> B -> E -> C -> F -> D -> G
mro方法
python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,如:
print(A.__mro__) # 在此用python3运行,广度优先
(, , , , , , , )
for i in A.__mro__:
print(i)