我是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 和 super(Super()P> mro python文档-Mro super()(查看Python文档-Super()) 返回一个代理对象,该对象将方法委派给父或类型类型类。这对于访问班级已覆盖的继承方法很有用。搜索顺序与getAttr()使用的搜索顺序相同,只是跳过了类型。 因此, super()将基于 mro ( 回到您的案件, 情况2 案例3
在Python中,MRO基于C3线性化。(Wiki和Python文档中有很多例子)
根据Python文件,它说.. classobject.__mro__
)搜索,并且可以通过parent类或类型的同学类来满足。
案例1
D.__mro__ = (D, C, B, A, object)
因此,输出将为D C B A
D的MRO与情况1中的D一样。((D, C, B, A, object)
)
但是, super()将在 c 上停止或满足,因为C类中的save()
未实现超级函数调用。
D的MRO等于(D, C, A, B, object)
。因此,当 super()到达A类中的Save()函数时,它将考虑满足。这就是为什么从未调用过B中保存功能的原因。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()调用。