之前,碰到一个很有意思的问题,调用super之后,并没有按照预期执行。大概是如下的:
#!/usr/bin/env python
# -*- coding=utf-8 -*-
class A(object):
def __init__(self):
print(type(self).mro())
def test(self):
print('A.test')
print(id(self))
print('A.test.end')
class B(A):
def test(self):
print('b.test')
print(id(self))
super(B, self).test()
print('b.test.end')
class C(A):
def test(self):
print('c.test')
print(id(self))
super(C, self).test()
print('c.test.end')
class D(B, C):
def test(self):
print('D.test')
print(id(self))
super(D, self).test()
print('d.test.end')
D().test()
运行结果如下:
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
D.test
4358651520
b.test
4358651520
c.test
4358651520
A.test
4358651520
A.test.end
c.test.end
b.test.end
d.test.end
可以看出,super的执行的顺序是Dstart->Bstart->Cstart->Astart->Aend->Cend->Bend>Dend,这个顺序与D的mro顺序一致。
这是由于super的实现导致的,其原理如下:
def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]
super会在inst的mro中查找到匹配到cls的下一个类,因此,从结果中也可以看到,super(x,self)中的self是同一个实例,因此,调用super时会按照mro的顺序执行下去。
这个点,可以作为面试题,考一下。实际工作中应该会遇到。