如果子类继承自两个单独的超类,而那两个超类又继承自同一个公共基类,那么就构成了钻石继承体系。这种继承体系很像竖立的菱形,也称作菱形继承。
class Base:
def __init__(self, value):
self.value = value
class One(Base):
def __init__(self, value):
Base.__init__(self, value)
self.value *= 2
class Two(Base):
def __init__(self, value):
Base.__init__(self, value)
self.value += 3
class Ways(One, Two):
def __init__(self, value):
One.__init__(self, value)
Two.__init__(self, value)
foo = Ways(5)
print(foo.value)
8
class Base:
def __init__(self, value):
self.value = value
class One(Base):
def __init__(self, value):
Base.__init__(self, value)
self.value *= 2
class Two(Base):
def __init__(self, value):
Base.__init__(self, value)
self.value += 3
class Ways(One, Two):
def __init__(self, value):
Two.__init__(self, value)
One.__init__(self, value)
foo = Ways(5)
print(foo.value)
10
通过上面我们可以看到,当Ways继承超类One Two的时候, 其结果是遵从在调用Base的init方法时的顺序的, 后面的一次调用的结果会覆盖前面一次的结果。
如果我们要解决这个问题就要运用到super方法,根据方法解析顺序(MRO)以标准化的流程来安排超类之间的初始化顺序,以保证能够达到顶端的同时,公共基类的方法只运行一次。
class Base:
def __init__(self, value):
self.value = value
class One(Base):
def __init__(self, value):
super(One, self).__init__(value)
self.value *= 2
class Two(Base):
def __init__(self, value):
super(Two, self).__init__(value)
self.value += 3
class Ways(One, Two):
def __init__(self, value):
super(Ways, self).__init__(value)
foo = Ways(5)
print(foo.value)
16
这个地方所得到的答案与我们预想的不一样,为什么呢?按照我们的设想, 应该是先运行到One方法,执行后得到数值10, 然后运行到Two方法,得到数值13,但实际并不是这样。
调用Way(5)时, 程序会先运行到One,然后运行到Two,但是对于它的内部我们做的运算,它并没有执行, 就像声明函数一样,声明了但是没有调用,直到程序找到最顶端的基类Base时, 它又反向的往回调用执行,所以先执行 +3, 然后执行 *2 , 最终得到结果16。
class Base:
def __init__(self, value):
self.value = value
class One(Base):
def __init__(self, value):
super(One, self).__init__(value * 2)
class Two(Base):
def __init__(self, value):
super(Two, self).__init__(value + 3)
class Ways(One, Two):
def __init__(self, value):
super(Ways, self).__init__(value)
foo = Ways(5)
print(foo.value)
13
如果将计算写入__init__方法,则就会先计算,再往更高的位置搜索。