我正在运行Python 2.5,因此此问题可能不适用于Python3。当您使用多重继承创建菱形类层次结构并创建最派生类的对象时,Python会执行Right Thing(TM)。它调用最派生类的构造函数,然后调用从左到右列出的父类,再调用祖父母。我熟悉Python的MRO;那不是我的问题。我很好奇从super返回的对象实际上如何正确地与父类中的super调用进行通信。考虑以下示例代码:
#!/usr/bin/python class A(object): def __init__(self): print "A init" class B(A): def __init__(self): print "B init" super(B, self).__init__() class C(A): def __init__(self): print "C init" super(C, self).__init__() class D(B, C): def __init__(self): print "D init" super(D, self).__init__() x = D()
该代码做直观的事情,它打印:
D init B init C init A init
但是,如果注释掉B的init函数中对super的调用,则不会调用A或C的init函数。这意味着B对super的调用以某种方式知道C在整个类层次结构中的存在。我知道super返回带有重载get运算符的代理对象,但是D的init定义中的super返回的对象如何将C的存在传达给B的init定义中的super返回的对象?超级调用的后续调用所使用的信息是否存储在对象本身上?如果是这样,为什么不是super而是self.super?
编辑:Jekke非常正确地指出它不是self.super,因为super是类的属性,而不是类的实例。从概念上讲,这是有道理的,但实际上,super也不是该类的属性!您可以通过在解释器中进行测试,方法是创建两个类A和B,其中B继承自A,然后调用dir(B)。它没有super或__super__属性。
dir(B)
super
__super__
我在下面提供了许多链接,这些链接比我所希望的更详细,更准确地回答了您的问题。但是,我也会用我自己的话回答您的问题,以节省您的时间。我会以分数为准-
__mro__
__init__
找到匹配方法后(例如在 BC1 类中),将调用该方法。 (此方法应该使用super,所以我假设它确实使用了-请参见Python的super很漂亮,但不能使用- 下面的链接)然后,该方法将在对象类的MRO中搜索下一个方法,即 BC1 。
重复漂洗直到找到并调用所有方法。
您的示例的说明
MRO: D,B,C,A,object
super(D, self).__init__()
B.__init__ 找到并打电话
B.__init__
super(B, self).__init__()
isinstance(self,B)=>假 isinstance(self,D)=>真
因此,MRO相同,但是搜索继续到B的右边,即C,A,对象被一个一个地搜索。下一个__init__被称为。
等等等等。
超级 http://www.python.org/download/releases/2.2.3/descrintro/#cooperation 的说明 使用超级 http://fuhm.net/super-harmful/ Pythons MRO算法 时需要注意的事项 : http ://www.python.org/download/releases/2.3/mro/ 超级的文档: http ://docs.python.org/library/functions.html本页 底部有一个关于超级的不错的部分: http:/ /docstore.mik.ua/orelly/other/python/0596001886_pythonian- chp-5-sect-2.html
我希望这有助于清除它。