Python3.6.1 中一个很有趣的问题探讨
最近遇到到一个问题,super 在多继承的类中只调用第一个类的函数。
代码如下
class A(object):
def __init__(self, **kwargs):
print('a1')
print('a', kwargs)
print('a2')
class B(object):
def init(self, **kwargs):
print(‘b1’)
print(‘b’, kwargs)
print(‘b2’)
class C(A, B):
def init(self, **kwargs):
print(‘c1’)
super(C, self).init()
print(‘c2’)
if name == ‘main’:
c = C()
结果是
c1
a1
a {}
a2
c2
这就很尴尬了,为什么不会出发 B().init 呢
Python3.6.1 中一个很有趣的问题探讨
我无法理解你的问题。
python2 貌似没问题啊
按声明时的父类顺序的
你可以自己贴代码去试试,我反正结果是我主题上说的,忽略了第二个超类
更新python<br>class A():<br> def __init__(self, **kwargs):<br> super().__init__()<br> print('a1')<br> print('a', kwargs)<br> print('a2')<br><br><br>class B():<br> def __init__(self, **kwargs):<br> super().__init__()<br> print('b1')<br> print('b', kwargs)<br> print('b2')<br><br><br>class C(A, B):<br> def __init__(self, **kwargs):<br> print('c1')<br> super().__init__()<br> print('c2')<br><br><br>if __name__ == '__main__':<br> c = C()<br>
这样的代码就能有下面的输出。。为什么,求有相关研究的高手给我一个答案<br>c1<br>b1<br>b {}<br>b2<br>a1<br>a {}<br>a2<br>c2<br>
这应该是 MRO 的问题,2.7.13 和 3.5.3 的结果和你的是一样的。
…这是 Python 的 MRO 机制决定的,Python3 用的是 C3 method,看看官方文档吧
问题是,为什么会这样,我后面贴出的代码本质上差不多,为什么又能正常的调用所有超类的初始化方法呢?
方便的话,麻烦你指点以下。
#8 两个代码是有区别的。
super 就是查找 mro 的下一个类。C 的 mro:[C, A, B, object],所以你新的代码就是按照这个顺序来调用__init__的。
A B 里面也要有 super (
mro
MRO C3 算法,简单来说就是深度优先遍历
#13 不是深度优先遍历。
super 并不是调用父类,而是调用 MRO 中的,具体要看 MRO 中顺序
python<br>class A(object):<br> def __init__(self, **kwargs):<br> super().__init__()<br> print('a1')<br> print('a', kwargs)<br> print('a2')<br> <br><br>class B(object):<br> def __init__(self, **kwargs):<br> print('b1')<br> print('b', kwargs)<br> print('b2')<br><br><br>class C(A, B):<br> def __init__(self, **kwargs):<br> print('c1')<br> super().__init__()<br> print('c2')<br><br><br>if __name__ == '__main__':<br> c = C()<br>
- 和 MRO 没关系,楼主说的是 B.__init__未调用
2. super 返回的是一个 delegate class,会去查找父类或者 sibling class,你这个情况在 AC 里用 super 就够了。原始的调用顺序 C 调了 super 找到 A,但是 A 没有调 super,所以没有找到它的 sibling B。
所以 best practice 是所有都用 super
用手机打的字,有点乱……
也和 MRO 有一丢丢关系啦,但是不是楼上所说的锅全丢给 MRO
楼上已经说了 MRO 没毛病
同意两位的意见。
Python 的 super()帮助文档引用了一个链接: http://rhettinger.wordpress.com/2011/05/26/super-considered-super/
这个文章的结论是 super().method()要能够 work,所有在祖先树上的 class 必须以合作模式来设计,这就是:
1. 被 super()调用的 method()必须存在
2. 调用者和被调用者必须要具有相同的参数(签名)
3. 每个出现的 method()必须也使用了 super()
我加了一些注释,我想这样就比较清楚了。
class A(object):
…def init(self, **kwargs):
…super().init() # 在 MRO(A,B,object)里面找到了下一级是 B. 调用 B.init(这句如果没有 B.__init__就调用不到)
…print(‘a1’)
…print(‘a’, kwargs)
…print(‘a2’)
class B(object):
…def init(self, **kwargs):
…super().init() # 在 MRO(B,object )里面找到了下一级是 object. 调用 object.init()
…print(‘b1’)
…print(‘b’, kwargs)
…print(‘b2’)
class C(A, B):
…def init(self, **kwargs):
…print(‘c1’)
…super().init() # 在 MRO(C,A,B,object )里面找到了下一级是 A. . 调用 A.init()
…print(‘c2’)
if name == ‘main’:
…print(C.mro) # MRO: (C,A,B,object)
…c = C()
谢谢。幸苦你帮我解决这个问题了。我最近遇到一个 pyqt5 的一个问题,能不能帮我解决?


