MRO in python when subclassing with multiple inheritance, using PyQt (QMainWindow) [duplicate]

半腔热情 提交于 2020-01-16 10:37:33

问题


I recently experienced a TypeError, that I didn't understood when I was subclassing a QMainWindow with PyQt5.

When creating two classes:

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

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

and then creating a Subclass of both, without any init arguments:

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

I get a TypeError when creating an instance of the subclass:

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

output:

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'

However, when changing the Order for the inheritance class SubClass( Base2, Base ): the code will run fine.


I read the post in How does Python's super() work with multiple inheritance? and Method Resolution Order but didn't found an answer on this.

(Also note that this is somewhat PyQt-specific, because I couldn't reproduce the problem with Base-classes entirely based on object)

Could someone give a clear explanation for this behaiviour?


回答1:


"It is always wrong to mix super with explict __init__ calls - all the base-classes must use super." - ekhumoro

I wasn't aware of this - thanks.

Furthermore, based on that, as well as on this answer and this wordpress article by Raymond Hettinger, it seems best practise to me to use **kwargs to pass all arguments trough the chain of super-calls and filter them part by part for each 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)

this way the MRO gets irrelevant for this example.


Research recommendation, for other newbies like me:

  • Raymond Hettinger:

    • Python’s super() considered super! (wordpress)
    • Super considered super! - PyCon 2015 (youtube)
  • How does Python's super() work with multiple inheritance (best on stackoverflow)

  • Super init vs. parent.__init__
  • Python super method and calling alternatives


来源:https://stackoverflow.com/questions/50016989/mro-in-python-when-subclassing-with-multiple-inheritance-using-pyqt-qmainwindo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!