类的继承
# 类的继承
Python 支持多父类的继承机制,所以需要注意圆括号中基类的顺序,若是基类中有相同的方法名,并且在子类使用时未指定,Python 会从左至右搜索基类中是否包含该方法。一旦查找到则直接调用,后面不再继续查找。
object
是 Python 为所有对象提供的父类,默认提供一些内置的属性、方法;可以使用 dir
方法查看。
dir(object)
1
# 新式类和旧式类
# 新式类
- 以
object
为父类的类,推荐使用 - 在 Python 3.x 中定义类时,如果没有指定父类,会默认使用
object
作为该类的父类 - 所以 Python 3.x 中定义的类都是新式类
# 旧式类
- 不以
object
为父类的类,不推荐使用 - 在 Python 2.x 中定义类,如果没有指定父类,不会使用
object
作为基类
# 区别
在多继承时,会影响到方法搜索顺序 MOR。
# 建议使用新式类
为了保证编写的代码能够同时在 Python2.x 和 Python 3.x 中运行,建议在定义类时,如果没有父类,也统一继承 object
。
class 类名(object):
pass
1
2
2
本文接下来讲的知识点也将会围绕新式类的继承机制展开。
# 继承机制
Python3 的继承机制(新式类)不同于 Python2(旧式类)。其核心原则是下面两条:
- 子类在调用某个方法或变量的时候,首先在自己内部查找,如果没有找到,则开始根据继承机制在父类里查找。
- 根据父类定义中的顺序,以深度优先的方式逐一查找父类。
# 第一个例子
设想有下面的继承关系:
class A(B, E):
pass
1
2
2
- A 继承 B 和 E
- B 继承 C,C 继承 D
- E 继承 F,F 继承 G
如下图所示:
(继承关系 - 第一个例子)
在这种继承结构关系中,子类在调用某个方法或变量的时候,搜索顺序是这样的(按下图中红色箭头路径指向):
(第一个例子的搜索顺序)
# 第二个例子
如果继承结构是这样的:类 D 和类 G 又同时继承了类 H,如下图所示:
(继承关系 - 第二个例子)
此时的搜索顺序是这样的(按下图中红色箭头路径指向):
(第二个例子的搜索顺序)
至于其它更错综复杂的继承情况,其实都能划分成上面两种情况。
# MRO 算法
- MRO(method resolution order)方法搜索顺序
- 对于单继承来说,MRO 很简单,从当前类开始,逐个搜索它的父类有没有对应的属性、方法
- 所以 MRO 更多用在多继承时判断方法、属性的调用路径
- Python 中针对类提供了一个内置属性
__mro__
可以查看方法搜索顺序
class A:
def test(self):
print("AAA-test")
class B:
def test(self):
print("BBB-test")
# 继承了三个类,B、A、还有默认继承的 object
class C(B, A):
...
# 通过类对象调用,不是实例对象!
print(C.__mro__)
# 输出结果
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
在搜索方法时,是按照 __mro__
的输出结果从左往右的顺序查找的。
(完)