了解 super 的工作原理[重复]
Posted
技术标签:
【中文标题】了解 super 的工作原理[重复]【英文标题】:Understanding how super works [duplicate] 【发布时间】:2014-11-01 15:22:34 【问题描述】:下面给出python程序。
class FooBase(object):
def foo(self): pass
class A(FooBase):
def foo(self):
super(A, self).foo()
print 'A.foo()'
class B(FooBase):
def foo(self):
super(B, self).foo()
print 'B.foo()'
class D(B):
def foo(self):
super(D, self).foo()
print 'D.foo()'
class C(A,D,B):
def foo(self):
super(C, self).foo()
print 'C.foo()'
c=C()
c.foo()
输出是
B.foo()
D.foo()
A.foo()
C.foo()
但是当我在程序下面运行时
class A1(object):
def get(self):
print 'A1'
class A2(object):
def get(self):
print 'A2'
class A3(object):
def get(self):
print 'A3'
class B2(A2):
def get(self):
super(B2,self).get()
print 'b2'
class B3(A3):
def get(self):
super(B3,self).get()
print 'b3'
class C3(B3):
def get(self):
super(C3,self).get()
print 'c3'
class Foo(C3, A1, B2):
def get(self):
super(Foo,self).get()
print 'Foo'
#print Foo.__mro__
Foo().get()
当我执行上述操作时,我得到如下输出
输出
A3
b3
c3
Foo
问题为什么A1.get()
和B2.get()
没有被调用。调用super有什么问题吗?
我期待输出
A3
b3
c3
A1
A2
b2
Foo
编辑:如果有人解释第一个示例和第二个示例之间的区别,那就太好了:)
【问题讨论】:
@jonrsharpe 这可能与此不同。我已经获得了三张重新开票。请重新开票,我正在寻求更好的答案。 【参考方案1】:您正在定义一个新的样式类,它是多个类的子类 (multiple inheritance)。因此,
对于老式类,唯一的规则是深度优先,从左到右。因此,如果在 DerivedClassName 中没有找到某个属性,则在 Base1 中搜索它,然后(递归地)在 Base1 的基类中搜索,并且只有在那里没有找到时,才在 Base2 中搜索,依此类推。
对于新型类,动态排序是必要的,因为所有多重继承的情况都表现出一种或多种菱形关系(其中至少一个父类可以从最底层的类通过多条路径访问)。例如,所有新式类都继承自 object,因此任何多重继承的情况都提供了多个到达 object 的路径。为了防止基类被多次访问,动态算法以保留每个类中指定的从左到右顺序的方式线性化搜索顺序
因此,在线性排序中,仅调用C3.get
,然后调用B3.get
,然后调用A3.get
如果您还想打印来自其他类的get
方法,请使用以下Foo
类:
class Foo(C3, A1, B2):
def get(self):
print '='*20 + 'Foo'
super(Foo, self).get()
print '='*20 + 'A1'
super(A1, self).get()
print '='*20 + 'B2'
super(B2, self).get()
那么,运行中的代码应该会输出正确的文本
$ python file.py
====================Foo
A3
b3
c3
====================A1
A2
b2
====================B2
A2
【讨论】:
我如何调用 A1 和 b2 get?python 如何知道使用哪种样式。第一个示例调用了所有类,而在第二个示例中只有一些。 问题是A1
、A2
和A3
在get
的实现中没有调用super
,破坏了调用链。要修复,他们需要这样做,以及从实现get
而不调用super
的单个基类(例如_getroot
)继承,这样你就不会结束尝试打电话给不存在的object.get
。
@sundarnatarajСундар 检查编辑
当你打电话给A1时,b2怎么来了?
有关如何计算订单的详细信息,请参阅this page。它包含一个指向原始论文的链接,该论文定义了编程语言 Dylan 的 C3 解析顺序(它使用更好的名称 next-method
作为其版本的 super
)。以上是关于了解 super 的工作原理[重复]的主要内容,如果未能解决你的问题,请参考以下文章