我正在运行Python 2.5,因此此问题可能不适用于Python3。当您使用多重继承创建菱形类层次结构并创建最派生类的对象时,Python会执行Right Thing(TM)。它调用最派生类的构造函数,然后调用从左到右列出的父类,再调用祖 parent 。我对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 调用的后续调用所使用的信息是否存储在对象本身上?如果是这样,为什么不是super而是self.super?

编辑:Jekke非常正确地指出它不是self.super,因为super是类的属性,而不是类的实例。从概念上讲,这是有道理的,但在实践中,super也不是该类的属性!您可以通过在解释器中进行测试,方法是创建两个类A和B,其中B继承自A,然后调用dir(B)。它没有super__super__属性。

最佳答案

我在下面提供了许多链接,这些链接比我所希望的更详细,更准确地回答了您的问题。但是,我也会用我自己的话回答您的问题,以节省您的时间。我会以分数为准-

  • super是内置函数,而不是属性。
  • Python中的每个类型(类)都有一个__mro__属性,该属性存储该特定实例的方法解析顺序。
  • 每个对super的调用都具有super(type [,object-or-type])的形式。让我们假设第二个属性目前是一个对象。
  • 在 super 调用的起点,对象属于Derived类的类型(说DC )。
  • super在指定为第一个参数的类(在本例中为DC之后的类)之后,在MRO的类中寻找与(在您的情况下为__init__)相匹配的方法。
  • 找到匹配方法(在类 BC1 中说)时,将调用它。
    (此方法应该使用super,因此我假设它确实使用了-请参阅Python的super很漂亮,但不能使用-下面的链接)
    然后,该方法将在对象的类的MRO中搜索下一个方法,即 BC1 的右侧。
  • 重复冲洗,直到找到并调用所有方法。

  • 您的示例的说明
     MRO: D,B,C,A,object
    
  • super(D, self).__init__()被调用。 isinstance(self,D)=>真
  • 在D右边的类中的MRO中搜索下一个方法

    找到B.__init__并称为


  • B.__init__调用super(B, self).__init__()

    isinstance(self,B)=>假
    isinstance(self,D)=>真
  • 因此,MRO相同,但是搜索继续在B的右侧进行,即,C,A,对象被一个一个地搜索。找到的下一个__init__被调用。
  • 等等。

  • super 的解释
    http://www.python.org/download/releases/2.2.3/descrintro/#cooperation
    使用 super 时需要注意的事项
    http://fuhm.net/super-harmful/
    Pythons MRO算法:
    http://www.python.org/download/releases/2.3/mro/
    super 文档:
    http://docs.python.org/library/functions.html
    此页面底部有一个关于super的不错的部分:
    http://docstore.mik.ua/orelly/other/python/0596001886_pythonian-chp-5-sect-2.html

    我希望这有助于清除它。

    10-07 19:02
    查看更多