超级尝试MRO中的每个班级

时间:2016-07-19 08:26:38

标签: python oop multiple-inheritance super

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 a出现在mixin b之前?
  2. super是否尝试MRO中的每个类(与返回找到第一个属性时搜索属性不同)?

2 个答案:

答案 0 :(得分:7)

不,super()没有尝试&#39; MRO中的每个班级。您的代码这些调用,因为每个调用的方法都包含另一个 super()调用。 Top.m()调用super().m(),解析为MixinB.m();然后又使用super()等等。

mixin a之前打印

mixin b,因为您在<{strong> super()调用后打印,因此MRO中的 last 元素首先执行。 super()调用只是另一种方法调用,因此在此类调用之后的print语句将无法执行,直到super().m()调用完成为止。

您的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()作为第一个参数的类;因此,对于任何给定的实例,MRO在层次结构的所有调用中都是稳定的。

如果您希望按照MRO调用的链接顺序执行打印语句,那么您必须在调用下一个{{1}之前放置print语句 MRO中的方法。

答案 1 :(得分:4)

此处没有尝试:您的致电订单是

  • Top.m()致电super(Top, self).m() MixinB.m()

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

  • MixinA.m()拨打super(MixinA, self).m() Base.m()

此时没有更多的超级电话,所以

  • Base执行print 'base'并返回(至MixinA.m()
  • MixinA.m()打印'mixin a'并返回(至MixinB.m()
  • MixinB.m()打印'mixin b'并返回(至Top.m())。
  • Top.m()打印'top'并返回给来电者。

打印件处于反向调用顺序,因为您正在超级调用链之后执行它们。