0

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)
Community
  • 1
  • 1
javanewbie
  • 281
  • 1
  • 3
  • 12
  • You can use `super`. In fact, that's exactly what it's for. – kindall Dec 25 '16 at 13:33
  • I've edited my question, could you take a look please? – javanewbie Dec 25 '16 at 13:49
  • This question is already been answered here (http://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with-multiple-inheritance) I suppose. You need to understand what MRO is. You can find the MRO tree of a child class by `ChildClass.__mro__`. super function works with Class bound and Instance bound proxies. – Eddie Dec 26 '16 at 04:58

1 Answers1

1

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().

Mike Müller
  • 82,630
  • 20
  • 166
  • 161