0

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
  • Your implementation is very buggy, so no clear exaplanation is possible. It is always wrong to mix super with explict __init__ calls - all the base-classes must use super. You also need to fix the handling of the mismatched signatures - see this answer and this answer to the first question you linked to. Once these problems are eliminated, the order of the base-classes doesn't matter. Commented Apr 25, 2018 at 19:52

1 Answer 1

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:

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.