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'>)
- 为什么
mixin a
在 mixin b
之前?
- 是否
super
尝试 MRO 中的每个 class(不同于在返回找到的第一个属性时搜索属性)?
不,super()
不 'try' 每个 class 在 MRO 中。您的代码 链接 调用,因为调用的每个方法都有 另一个 super()
调用。 Top.m()
调用 super().m()
,解析为 MixinB.m()
;依次使用 super()
等
mixin a
在 mixin 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
,然后是 MixinB
,Top
最后打印。
请注意,使用的是 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。
打印的调用顺序是相反的,因为您是在超级调用链之后执行它们。
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'>)
- 为什么
mixin a
在mixin b
之前? - 是否
super
尝试 MRO 中的每个 class(不同于在返回找到的第一个属性时搜索属性)?
不,super()
不 'try' 每个 class 在 MRO 中。您的代码 链接 调用,因为调用的每个方法都有 另一个 super()
调用。 Top.m()
调用 super().m()
,解析为 MixinB.m()
;依次使用 super()
等
mixin a
在 mixin 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
,然后是 MixinB
,Top
最后打印。
请注意,使用的是 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。
打印的调用顺序是相反的,因为您是在超级调用链之后执行它们。