使用PyQt(QMainWindow)进行多继承子类化时python中的MRO

时间:2018-04-25 08:01:44

标签: python pyqt pyqt5 multiple-inheritance method-resolution-order

我最近遇到了TypeError,当我使用PyQt5QMainWindow子类化时,我不明白。

创建两个类时:

class Base (QMainWindow):
    def __init__(self):
        super(Base, self).__init__(None)

class Base2 (object):
    def __init__(self, a, b):
        pass

然后创建两者的子类,没有任何init参数:

class SubClass( Base, Base2 ):
    def __init__(self):
        Base.__init__(self)
        Base2.__init__(self, 0,0)

在创建子类的实例时,我得到一个TypeError:

from PyQt5.QtWidgets import QApplication, QMainWindow    
app = QApplication([])
print( SubClass() )

输出:

Traceback (most recent call last):
    print(SubClass())
    Base.__init__(self)
    super(Base, self).__init__(None)
TypeError: __init__() missing 2 required positional arguments: 'a' and 'b'

但是,在更改继承订单class SubClass( Base2, Base ):时,代码运行正常。

我在How does Python's super() work with multiple inheritance?Method Resolution Order中阅读了该帖子,但没有找到答案。

(另请注意,这在某种程度上是PyQt特有的,因为我无法完全基于object重现基类的问题)

有人可以对这种行为做出明确的解释吗?

1 个答案:

答案 0 :(得分:1)

  

“将super与explict __init__调用混合在一起总是错误的 - 所有基类必须使用super。” - ekhumoro

我没有意识到这一点 - 谢谢。

此外,基于此,以及Raymond Hettinger的this answerthis wordpress article,我最好使用**kwargs通过超链接传递所有参数-calls并逐个过滤每个init:

class Base (QMainWindow):
    def __init__(self, parent, **kwargs):
        super().__init__(parent, **kwargs)

class Base2 (object):
    def __init__(self, a, b, **kwargs):
        super().__init__(**kwargs)

class SubClass(Base, Base2): # order can be switched now
    def __init__(self):
        super().__init__(a=0, b=0, parent=None)
通过这种方式,MRO与此示例无关。

研究建议,对于像我这样的其他新手: