super是否在MRO中尝试每个class

Does super try each class in MRO

class Base(object):
    def m(self):
        print 'base'


class MixinA(Base):
    def m(self):
        super(MixinA, self).m()
        print 'mixin a'


class MixinB(Base):
    def m(self):
        super(MixinB, self).m()
        print 'mixin b'


class Top(MixinB, MixinA, Base):
    def m(self):
        super(Top, self).m()
        print 'top'


t = Top()
t.m()

这会打印:

base
mixin a
mixin b
top

我对很多事情感到惊讶。 Top 的第一个 MRO 是 (<class 'Top'>, <class 'MixinB'>, <class 'MixinA'>, <class 'Base'>, <type 'object'>)

  1. 为什么 mixin amixin b 之前?
  2. 是否 super 尝试 MRO 中的每个 class(不同于在返回找到的第一个属性时搜索属性)?

不,super() 不 'try' 每个 class 在 MRO 中。您的代码 链接 调用,因为调用的每个方法都有 另一个 super() 调用。 Top.m() 调用 super().m(),解析为 MixinB.m();依次使用 super()

mixin amixin b 之前打印,因为您在 调用 super() 之后打印,所以 last MRO中的元素先执行。 super() 调用 只是另一个方法调用 ,因此在 super().m() 调用完成之前不会执行此类调用之后的 print 语句.

您的 MRO 如下:

>>> type(t).__mro__
(<class '__main__.Top'>, <class '__main__.MixinB'>, <class '__main__.MixinA'>, <class '__main__.Base'>, <type 'object'>)

所以自然地 Base.m() 最后被调用并首先打印,然后是 MixinA,然后是 MixinBTop 最后打印。

请注意,使用的是 self 的 MRO,而不是作为第一个参数传递给 super() 的 class 的;因此,对于任何给定实例,MRO 在层次结构中的所有调用中都是稳定的。

如果您希望打印语句按照 MRO 调用的链接顺序执行,则必须将 print 语句放在 之前 调用下一个m() MRO 中的方法。

不涉及尝试,这里:您的调用顺序是

  • Top.m() 调用 super(Top, self).m()MixinB.m().

  • MixinB.m() 立即调用 super(MixinB, self).m(),当用 type(self) == Top 调用时,它是 MixinA.m()super() 使用 self 对象的 MRO,因此我们需要查看 Top,而不是独立的 MixinB.

  • MixinA.m() 调用 super(MixinA, self).m()Base.m().

此时没有更多的超级调用,所以

  • Base 执行 print 'base' 和 returns(到 MixinA.m()
  • MixinA.m() 打印 'mixin a' 和 returns(到 MixinB.m()
  • MixinB.m() 打印 'mixin b' 和 returns(到 Top.m())。
  • Top.m() 向调用者打印 'top' 和 returns。

打印的调用顺序是相反的,因为您是在超级调用链之后执行它们。