钻石继承和MRO



我是Mro的新手,并且在找出这些输出的逻辑时遇到问题。

案例1:

class A(object):
  def save(self):
      print "A"
class B(A):
    def save(self):
        print "B"
        super(B, self).save()
class C(A):
  def save(self):
      print "C"
      super(C, self).save()

class D(C, B):
    def save(self):
        print "D"
        super(D,self).save()
D().save()

输出:

D
C
B
A

我的问题是super(C)如何调用B.save()

按照MRO:super(C, self)与" C的基类"有关,而是关于C的MRO列表中的下一个类。但是C的MRO列表中没有B

案例2:

class A(object):
  def save(self):
      print "A"
class B(A):
    def save(self):
        print "B"
        super(B, self).save()
class C(A):
  def save(self):
      print "C"
      # removed super call here
class D(C, B):
    def save(self):
        print "D"
        super(D,self).save()
D().save()

输出:

D
C

案例3:

class A(object):
  def save(self):
      print "A"
class B(object):
    #inherits object now instead of A
    def save(self):
        print "B"
        super(B, self).save()
class C(A):
  def save(self):
      print "C"
      super(C, self).save()
class D(C, B):
    def save(self):
        print "D"
        super(D,self).save()
D().save()

输出:

D
C
A

问题

如果B不是从A继承,而是直接object

如何影响MRO?

有人可以解释此背后的原因吗?

为了解决这些问题,您首先需要了解 mro super(Super()P>

mro python文档-Mro
在Python中,MRO基于C3线性化。(Wiki和Python文档中有很多例子)

super()(查看Python文档-Super())
根据Python文件,它说..

返回一个代理对象,该对象将方法委派给父类型类型类。这对于访问班级已覆盖的继承方法很有用。搜索顺序与getAttr()使用的搜索顺序相同,只是跳过了类型。

因此, super()将基于 mro classobject.__mro__)搜索,并且可以通过parent类或类型的同学类来满足。

回到您的案件,
案例1
D.__mro__ = (D, C, B, A, object)
因此,输出将为D C B A

情况2
D的MRO与情况1中的D一样。((D, C, B, A, object)
但是, super()将在 c 上停止或满足,因为C类中的save()未实现超级函数调用。

案例3
D的MRO等于(D, C, A, B, object)。因此,当 super()到达A类中的Save()函数时,它将考虑满足。这就是为什么从未调用过B中保存功能的原因。

此外,如果将D的继承序列从C,B转换为B,C。(class D(C, B)class D(B, C))。然后,当您致电D().save()时,输出将为 d b ,因为D.__mro__ = (D, B, C, A, object)和Super()将在B级B中满足。

此外,从我的理解中, super()不是迫使子类对象在父类中调用 ALL 覆盖功能的函数。如果您想强迫您的课程在其父类中调用所有覆盖功能。您可以尝试做类似:

的事情
class Base(object):
    def method(self):
        print('Base-method')
class Parent(object):
    def method(self):
        print('Parent-method')
class Child(Parent):
    def method(self):
        print('Child-method')
        super(Child, self).method()
class GrandChild(Child, Base):
    def method(self):
        print('GrandChild-method')
        for base in GrandChild.__bases__:
            base.method(self)
        #super(GrandChild, self).method()

然后,当您调用`

GrandChild-method
Child-method
Parent-method
Base-method

注意:
GrandChild.__bases__仅包含班级和班级基础

ps。
通过在上面说满足,我的意思是没有更多的super()调用。

相关内容

  • 没有找到相关文章

最新更新