整体
假设所有东西都来自object(如果不是你自己的),Python会根据你的类继承树计算一个方法解析顺序(MRO)。MRO满足3个性质:
一个阶层的孩子比他们的父母更重要
左父母先于右父母
一个类在MRO中只出现一次
如果不存在这样的顺序,Python将出错。它的内部工作原理是类祖先的C3线性化。点击这里阅读:https://www.python.org/download/releases/2.3/mro/
当一个方法被调用时,该方法在MRO中第一次出现就是被调用的方法。任何没有实现该方法的类都将被跳过。在该方法中对super的任何调用都将调用MRO中该方法的下一次出现。因此,在继承中放置类的顺序以及在方法中放置super调用的位置都很重要。
注意,你可以通过使用__mro__方法在python中看到MRO。
例子
下面所有的例子都有菱形类继承,如下所示:
Parent
/ \
/ \
Left Right
\ /
\ /
Child
MRO是:
孩子
左
正确的
父
您可以通过调用Child来测试这一点。__mro__,返回:
(__main__.Child, __main__.Left, __main__.Right, __main__.Parent, object)
每一种方法都以超第一
class Parent(object):
def __init__(self):
super(Parent, self).__init__()
print("parent")
class Left(Parent):
def __init__(self):
super(Left, self).__init__()
print("left")
class Right(Parent):
def __init__(self):
super(Right, self).__init__()
print("right")
class Child(Left, Right):
def __init__(self):
super(Child, self).__init__()
print("child")
孩子()输出:
parent
right
left
child
在每个方法中都有超级最后
class Parent(object):
def __init__(self):
print("parent")
super(Parent, self).__init__()
class Left(Parent):
def __init__(self):
print("left")
super(Left, self).__init__()
class Right(Parent):
def __init__(self):
print("right")
super(Right, self).__init__()
class Child(Left, Right):
def __init__(self):
print("child")
super(Child, self).__init__()
孩子()输出:
child
left
right
parent
当不是所有类都调用super时
如果不是继承链中的所有类都调用super,那么继承顺序最重要。例如,如果Left不调用super,那么Right和Parent上的方法永远不会被调用:
class Parent(object):
def __init__(self):
print("parent")
super(Parent, self).__init__()
class Left(Parent):
def __init__(self):
print("left")
class Right(Parent):
def __init__(self):
print("right")
super(Right, self).__init__()
class Child(Left, Right):
def __init__(self):
print("child")
super(Child, self).__init__()
孩子()输出:
child
left
或者,如果Right没有调用super, Parent仍然被跳过:
class Parent(object):
def __init__(self):
print("parent")
super(Parent, self).__init__()
class Left(Parent):
def __init__(self):
print("left")
super(Left, self).__init__()
class Right(Parent):
def __init__(self):
print("right")
class Child(Left, Right):
def __init__(self):
print("child")
super(Child, self).__init__()
在这里,Child()输出:
child
left
right
调用特定父节点上的方法
如果你想访问一个特定父类的方法,你应该直接引用这个类,而不是使用super。Super是关于遵循继承链,而不是到达特定类的方法。
下面是如何引用一个特定的父方法:
class Parent(object):
def __init__(self):
super(Parent, self).__init__()
print("parent")
class Left(Parent):
def __init__(self):
super(Left, self).__init__()
print("left")
class Right(Parent):
def __init__(self):
super(Right, self).__init__()
print("right")
class Child(Left, Right):
def __init__(self):
Parent.__init__(self)
print("child")
在这种情况下,Child()输出:
parent
child