超级尝试先生的每一节课吗

2024-04-23 15:17:10 发布

您现在位置:Python中文网/ 问答频道 /正文

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中的每个类(与返回找到的第一个属性时搜索属性不同)?你知道吗

Tags: selfbase属性objecttopdefmixinclass
2条回答

不,super()不“尝试”MRO中的每个类。您的代码链接了调用,因为每个被调用的方法都有另一个调用。Top.m()调用super().m(),后者解析为MixinB.m();后者又使用super(),以此类推

mixin amixin b之前打印,因为您在super()调用之后打印,所以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,然后是MixinB,最后是Top。你知道吗

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

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

这里不涉及尝试,您的呼叫顺序是

  • 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'并返回(到MixinA.m()
  • MixinA.m()打印'mixin a'并返回(到MixinB.m()
  • MixinB.m()打印'mixin b'并返回(到Top.m())。你知道吗
  • Top.m()打印'top'并返回给调用者。你知道吗

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

相关问题 更多 >