Understanding python's super method, Why D().test() will return 'B->C' and not 'B-->A'
我在这里研究了关于python的super()方法的其他问题,但是我仍然发现很难理解整个概念。
我也在看《专业python》一书中的例子。
这里引用的例子是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | class A(object): def test(self): return 'A' class B(A): def test(self): return 'B-->' + super(B, self).test() class C(A): def test(self): return 'C' class D(B, C): pass >>> A().test() 'A' >>> B().test() 'B-->A' >>> C().test() 'C' >>> D().test() 'B-->C' >>> A.__mro__ (__main__.A, object) >>> B.__mro__ (__main__.B, __main__.A, object) >>> C.__mro__ (__main__.C, __main__.A, object) >>> D.__mro__ (__main__.D, __main__.B, __main__.C, __main__.A, object) |
为什么要执行d().test(),我们得到的输出是'b->c'而不是'b->a'
书中的解释是
In the most common case, which includes the usage shown here, super() takes two arguments: a
class and an instance of that class. As our example here has shown, the instance object determines
which MRO will be used to resolve any attributes on the resulting object. The provided class determines
a subset of that MRO, because super() only uses those entries in the MRO that occur after the class
provided.
我仍然觉得这个解释有点难以理解。这可能是一个重复的问题,类似的问题已经被问过很多次了,但是如果我理解了这一点,我可能能够更好地理解其他问题。
使用uu init_uu()方法了解python super()。
"super"在python中做什么?
python,继承,super()方法
[Python]:被super()迷惑了
如果您想知道为什么python选择这个特定的mro算法,可以在邮件列表存档中进行讨论,并在python 2.3方法解析顺序中简要总结。
但事实上,归根结底是这样的:在处理多重继承时,python 2.2的方法分辨率被破坏了,任何人建议修复它的第一件事就是从dylan中借用c3算法,没有人对此有任何问题,也没有人提出更好的建议,因此python使用c3。
如果你对c3相对于其他算法的一般优势(和劣势)更感兴趣…
布伦巴恩和弗洛雷克的回答为这个问题提供了基础。python的super()被认为是super!雷蒙德·赫廷格的博客以同样的方式进行了更长更详细的讨论,绝对值得一读。
Dylan的单调超类线性化是描述该设计的原始论文。当然,Dylan是一种与Python非常不同的语言,这是一篇学术论文,但其基本原理仍然很好。
最后,python 2.3方法解析顺序(上面链接的相同文档)对其好处进行了一些讨论。
而且,您还需要学习很多关于可选方案的知识,以及它们是如何使用的以及不适合于Python的,以便进一步了解。或者,如果你想要更深入的信息,你需要问更具体的问题。
最后,如果你在问"如何"的问题:
当您调用
这里的关键是,MRO是基于
因此,
但这并不能解释MRO是如何工作的,只是它的作用。
首先,请注意,
方法基本上是一个对象,包含
所以,我们的三个例子都有相同的
那么,
每当编写
1 2 3 4 5 6 7 8 | def getattr(obj, name): for cls in obj.__class__.__mro__: try: desc = cls.__dict__[name] except KeyError: pass else: return desc.get(obj.__class__, obj) |
最后的那个
简而言之,该方法的分辨率顺序大致为"宽度优先"。也就是说,它在进入任何一个超类之前,都要经过给定祖先级别的所有基类。因此,如果D继承B和C,两者都继承A,那么MRO总是在A之前有B和C。
另一种思考方法是,如果命令是b->a,那么
这里可以找到更详细的解释。您还可以通过谷歌搜索或搜索stackoverflow来查找关于"python方法解析顺序"或"python mro"的问题。
当每个类只有一个父类(单继承)时,
但是当您使用多个基类时,就像您在示例中所做的那样,事情开始变得更加复杂。在这种情况下,python确保如果在任何地方调用
一个(有些荒谬的)例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Animal(object): def make_sounds(self): pass class Duck(Animal): def make_sounds(self): print 'quack!' super(Duck, self).make_sounds() class Pig(Animal): def make_sounds(self): print 'oink!' super(Pig, self).make_sounds() # Let's try crossing some animals class DuckPig(Duck, Pig): pass my_duck_pig = DuckPig() my_duck_pig.make_sounds() # quack! # oink! |
你想让你的