新式类和经典类的继承原理,super的用法
day29
继承顺序
-
Python的类可以继承多个类,Java和C#中则只能继承一个类
-
Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先

当类是经典类时,多继承情况下,会按照深度优先方式查找
当类是新式类时,多继承情况下,会按照广度优先方式查找
在Python3中所有的都是新式类
在Python2中才有新式类和经典的区分,写法上的区分:如果当前类或父类继承了object类,那么该类便是新式类,否则便是经典类。

例子1:
继承关系如下图:

查找顺序是:
F-->D-->B-->X-->E-->C-->A-->object
例子2:
继承关系如下图:

查找顺序是:
F-->D-->B-->X-->E-->C--Y-->object
例子3:
继承关系如下图:

查找顺序是:
H-->E-->B-->F-->C-->G-->D-->A-->object
Python2经典类继承顺序:深度优先
例子:
继承关系如下:

查找顺序是:
F-->D-->B-->X-->A-->E-->C
继承原理(python如何实现的继承)
python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如:
print(F.mro()) # F.mro()与F.__mro__一样。
结果:
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,他实际上就是合并所有父类的MRO列表,并遵循如下三条准则:
-
子类会先于父类被检查
-
多了父类会根据他们在列表中的顺序被检查
-
如果对下一个类存在两个合法的选择,选择第一个父类
新式类:
class A(object):
def test(self):
print('from A')
class B(A):
def test(self):
print('from B')
class C(A):
def test(self):
print('from C')
class D(B):
def test(self):
print('from D')
class E(C):
def test(self):
print('from E')
class F(D, E):
# def test(self):
# print('from F')
pass
print(F.__mro__) # 只有新式才有这个属性可以查看线性列表,经典类没有这个属性
print(F.mro()) # F.mro()与F.__mro__一样。
结果:
(<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
super的用法
super在python2中的用法:
super(自己的类名,self).父类的函数名字
super只能用于新式类
在Python3中:
class People:
def __init__(self, name, sex, age):
self.name = name
self.sex = self
self.age = age
def walk(self):
print("%s is walking.." % (self.name))
class Chinese(People):
country = "China"
def __init__(self, name, sex, age, language="Chinese"):
# People.__init__(self, name, sex, age) # 之前的写法
super().__init__(name, sex, age) # super用法,调的父类的绑定办法,所以不需要传self
# super(Chinese,self).__init__(name, sex.age) # python2的写法,并且父类必须是新式类People要继承object,People(object)
self.langueage = language
c = Chinese("alex", "male", 18)
c.walk()
输出:
alex is walking..

共有 0 条评论