
相关代码 1:
class A(object): def show(self): print ('init A...') class B(A): def show(self): super(B, self).show() print('init B...') class C(A): def show(self): # super(C, self).show() print('init C...') class D(B, C): def show(self): super(D, self).show() print('init D...') d = D() d.show() 输出的结果是:
init C... init B... init D... 这里想问的是为什么没有经过 A,输出 init A...
相关代码 2:
class A(object): def show(self): print ('init A...') class B(A): def show(self): super(B, self).show() print('init B...') class C(A): def show(self): # super(C, self).show() print('init C...') class D(C, B): #继承类和代码 1 中的顺序相反 def show(self): super(D, self).show() print('init D...') d = D() d.show() 输出的结果是:
init C... init D... 这里想问的是为什么 B 中的方法没有被调用? 还有的就是新式类的 MRO 算法采用广度优先搜索。在这里是怎么调用的?
谢谢各位大佬
1 Outliver0 Nov 13, 2018 你可以打印一下__mro__查看顺序 |
2 coroutine Nov 13, 2018 对于, “为什么没有经过 A,输出 init A... ” 你可以参考 Python Cookbook,第 8 章关于 super 的描述。 类 B 里 show 的 super,实际上调用的是类 C 的 show。 而类 C 的 super 已经被你注释掉了。 |
3 Outliver0 Nov 13, 2018 第一次的 mro 顺序为 [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>], super(D, self).show()----> super(B, self).show()------>C.show() C 已经有 show()方法,所有打印顺序为 init C...,init B...,init D... 第二次的 mro 顺序为 [<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>], super(D, self).show() ----->C.show() C 已经有 show()方法,所有打印顺序为 init C... ,init D... |
4 coroutine Nov 13, 2018 super 的调用顺序实际上,与最终该类的 MRO 的顺序有关。你可以从 D.__mro__ 打印出类 D 的类继承顺序。 比如您给出的两个例子,的 MRO 分别为 (__main__.D, __main__.B, __main__.C, __main__.A, object); (__main__.D, __main__.C, __main__.B, __main__.A, object) 如何生成 MRO 顺序,就是 cookbook 里提到的 https://en.wikipedia.org/wiki/C3_linearization 了。 |
5 coroutine Nov 13, 2018 您可以参阅 Python Cookbook Chapter 8: 8.7: Calling a Method on a Parent Class 这一小节。 |
6 liukeai7777 Nov 13, 2018 D 的 mro 是 (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>) init C... init B... init D... 所以 super 方法的查找顺序就 DBCA 多以第一个例子 第一步运行到 class D 的 show 方法 , class D show 第一句: [super(D, self).show() 查找 B 的 show 方法。运行到 class B 的 show 方法,classB show 执行第一句:super(B, self).show() 然后又找到 class C 的 show 方法 于是打印第一句 init C,执行第二句 init C ] class D 的 show 第二句 打印 init C 同理第二个例子 MRO 是 DCBA |
7 king1101 OP 多谢各位大佬,我已经理解了,其实走入了一个误区,认为 super 就是调用父类的方法,其实 super 指的是 MRO 的下一个类,和父类没有实质关联。 |
8 zxcvsh Nov 13, 2018 via iPhone 百度一下,拓扑排序,好像是这个关键字;图解说明继承检索的顺序很明了 |
9 liukeai7777 Nov 13, 2018 D 的 mro 是 (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>) init C... init B... init D... 所以 super 方法的查找顺序就 DBCA 多以第一个例子 第一步运行到 class D 的 show 方法 , class D show 第一句: [super(D, self).show() 查找 B 的 show 法。运行到 class B 的 show 方法,classB show 执行第一句:super(B, self).show() 然后又找到 class C 的 show 方法 于是打印第一句 init C,执行第二句 init B] class D 的 show 第二句 打印 init D 同理第二个例子 MRO 是 DCBA |
10 seven777 Nov 13, 2018 给楼主一个解药: (我不是程序员,但我觉得如此...) 无论当前的任何编程语言,原理基本想通; 虽然不同语言有不同的“继承”处理方式,但原理相同。 统一标准是: 1,没有什么需求非得复杂的继承来实现,如果有,你设计错了; 2,如果一个继承关系你搞不明白,不是你技术问题,是设计错了,换思路吧; 3,“事不过三”在编程中应该是重要思想,比如继承层级不要超过三层,继承源头不要超过三个,再比如 if,while,等判断关系嵌套不要超过三层... 我瞎说的,但觉得应该如此 |
11 ticotico Nov 13, 2018 via Android 不是把 C 中 super 注释掉了么,D 中的 super 是按 mro 查找 MRO 中下一位的,MRO 在新式类中按的是 bfs 来拍得,最近刚接触 mro 不知道说得对不对,各位大佬轻拍 |
12 RomanCavalry Nov 15, 2018 这个就需要了解 Python MRO 的历史了,参考: http://python.jobbole.com/85685/ |