javanewbie
javanewbie

Reputation: 301

Python - Base class' constructor is overriden

As explained in How does Python's super() work with multiple inheritance?, super can be used in multiple inheritance as well, as it will look for the attribute in both parents. But what attribute? The subclass already includes a super (if you look at the code below). How do I specify the attribute I want? I want Error's constructor.

class Error(object):
    def __init__(self, values):
        self.values = values

class AddDialog(sized_controls.SizedDialog, Error):
    def __init__(self, *args, **kwargs):
        Error.__init__(self, *args)
        super(AddDialog, self).__init__(*args, **kwargs)

Upvotes: 0

Views: 52

Answers (1)

Mike Müller
Mike Müller

Reputation: 85462

It is as easy as just trying it out:

class Error(object):
    def __init__(self, values):
        self.values = values
        print('Error')

class SizedDialog(object):
    def __init__(self, values):
        self.values = values
        print('SizedDialog')

class AddDialog(SizedDialog, Error):
    def __init__(self, *args, **kwargs):
        print('AddDialog')
        Error.__init__(self, *args)
        super(AddDialog, self).__init__(*args, **kwargs)

Now, super() is nothing else but going along the method resolution order (MRO) which you can get with mro():

>>> AddDialog.mro()
[__main__.AddDialog, __main__.SizedDialog, __main__.Error, object]

So, in your case you call the __init__() of Error explicitly first. Then super() will, in this specific case, find the __init__() of SizedDialog because it comes before Error in the MRO.

>>> a = AddDialog(10)
AddDialog
Error
SizedDialog

If you only use super() (no call to __init__() of Error), you get only the __init__() of SizedDialog:

class AddDialog(SizedDialog, Error):
    def __init__(self, *args, **kwargs):
        print('AddDialog')
        super(AddDialog, self).__init__(*args, **kwargs)

>>> a = AddDialog(10)
AddDialog
SizedDialog

Finally, if you only call the __init__() of Error, it is the only __init__() that is called.

class AddDialog(SizedDialog, Error):
    def __init__(self, *args, **kwargs):
        print('AddDialog')
        Error.__init__(self, *args)

>>> a = AddDialog(10)
AddDialog
Error

So your question:

But what attribute?

has the answer:

The one you call.

It does not matter if you hard-wire the class, as done with Error, or let super() find the appropriate parent class, i.e. the next one in the MRO. The only difference is that super() might call the __init__()of the grandparent class if the parent class does not have an __init__(). But this is the intended behavior of super().

Upvotes: 1

Related Questions