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