我是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列表中的下一个类。但C的MRO列表中没有C。
案例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是如何影响的?
有人能解释一下背后的原因吗?
发布于 2017-06-14 03:49:53
为了解决这些问题,您首先需要了解MRO和超级()是如何工作的。
MRO Python文档- MRO
在Python中,MRO是基于C3线性化的。( wiki和python文档中有许多示例)
超级()(查看Python超级())
根据Python文档,它说..。
返回代理对象,该对象将方法调用委托给类型为类型的父类或兄弟类。这对于访问已在类中重写的继承方法非常有用。搜索顺序与getattr()使用的顺序相同,只是类型本身被跳过。
因此,超级()将基于MRO (classobject.__mro__)进行搜索,并且它将被类型的父类或兄弟类所满足。
回到你的案子,
案例1
D.__mro__ = (D, C, B, A, object)
因此,输出将是D C B A
案例2
在案例1中,D的MRO与D相同。((D, C, B, A, object))
但是,超级()将停止或满足于C,因为C类中的save()没有实现超级函数调用。
案例3
D的MRO等于(D, C, A, B, object)。因此,当超级()达到A类中的save()函数时,它会认为满足。这就是为什么从来没有调用B中的save函数的原因。
此外,如果将D的继承序列从C、B转换到B、C (class D(C, B)到class D(B, C))。然后,当您调用D().save()时,输出将是D B,因为在B类将满足D.__mro__ = (D, B, C, A, object)和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()时,输出将是:
GrandChild-method
Child-method
Parent-method
Base-method注意:
GrandChild.__bases__只包含类子类和类基
PS。
通过在上面说满意,我的意思是不再有超级()调用。
https://stackoverflow.com/questions/42665175
复制相似问题