You can try multiple ways such as:
GrandParent.__init__(self)
super().super().__init__(self)
super(GrandParent, self).__init__()
but the error will still be there either as:
super-init-not-called
- or
bad-super-call (super(GrandParent, self)...)
- or even as useless super call to the immediate parent.
I suppose it's meant as a warning for not initializing the immediate class in the class __mro__ by mistake if you work with inheritance and you can to turn off it with a pylint disable:
# pylint: disable=super-init-not-called
but you are messing with the __mro__ chain by such calls.
What you can do is allow cascading through the Child.__mro__ items upward i.e. Child -> Parent -> GrandParent (-> object) while skipping by class reference in an __init__:
class Parent(GrandParent):
def __init__(self):
super().__init__()
if self.__class__ == Child:
return
which does not trigger the PyLint warnings and allows the correct behavior explicitly and without skipping any required items in __mro__.
IMO it's much cleaner preserving the __mro__ which seems what PyLint's intent is as well by super-init-not-called warning. On the other hand, it's kind of tricky and hides the code in a completely different class and that will make the debugging in the future annoying if some properties from Parent will be missing and no comment/disable warning are present in Child class.
If you want to pull the methods out of the GrandParent class only, simply go with the "mixins" classes which is what Django REST Framework is using and don't write any __init__ for those (or if, then don't forget super().__init__() to continue in __mro__ chain!).
class GrandParent:
def __init__(self):
print("> GrandParent __init__()")
class Mixin:
def mymethod(self):
print("Hey")
class Parent(Mixin, GrandParent):
def __init__(self):
print("> Parent __init__()")
super().__init__()
class Child(Mixin, GrandParent):
def __init__(self):
print("> Child __init__()")
super().__init__()
Child().mymethod()
# > Child __init__()
# > GrandParent __init__()
# Hey
Parent().mymethod()
# > Parent __init__()
# > GrandParent __init__()
# Hey
which will basically be the same situation you have with Child -> Parent -> GrandParent but Mixin itself doesn't have (any useful) __init__ which will cause your code only from GrandParent to execute due to Mixin.__init__() being empty hence doing visually the same thing as with if self.__class__ == Child: return but without any hacks + with increased readability.