问题
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