0

I've read the most similar question on SO to my question, which was about single-parent inheritance and the only answer that mentioned multi-parent inheritance advised the reader to use the static form of calling that method (SomeSuperClass.someMethod(self, args)), which, as pointed out in the comments is not always clean.

I am asking for a way to call a specific method someMethod of a specific superclass SomeSuperClass dynamically, as such:

class SomeSuperClass():
    def someMethod(self, args):
        print("Hello,", end="")

class Subclass(SomeSuperClass, OtherSuperClass):
    def someMethod(self, args):

        # static calling (I do not want this solution)
        SomeSuperClass.someMethod(self, args)

        # dynamic calling (I want this one)
        (my SomeSuperClass-ness).someMethod(args)

        print("world!")

This is the code I actually tested and want to work:

class Something():
    def __init__(self, a, b) -> None:
        self.sum = a+b


class SomethingElse():
    def __init__(self, c, d) -> None:
        self.product = c * d


class Both(Something, SomethingElse):
    def __init__(self, a, b) -> None:

        # sadly this does not work
        super(Something, self).__init__(a, b)
        super(SomethingElse, self).__init__(a, b)

        # the following works, but is static and does not use super
        # Something.__init__(self, a, b)
        # SomethingElse.__init__(self, a, b)

b = Both(10, 20)

print(b.sum, b.product)

Running this code results in the following error:

TypeError: object.__init__() takes exactly one argument (the instance to initialize)

Apparently it's trying to call the __init__ of object. How do I use super correctly in this scenario for it to actually call the appropriate __init__s?

SMMH
  • 310
  • 1
  • 13
  • For clarification: _dynamic_ calling =`object.method(args)`, whereas _static_ calling = `Class.method(object, args)` – SMMH May 16 '21 at 13:58

1 Answers1

0

The super() function will delegate to the parent after the one you've specified - see here, specifically the following remark:

The object-or-type determines the method resolution order to be searched. The search starts from the class right after the type.

So to use it correctly, you should use super() to refer to Something, and super(Something, self) to refer to SomethingElse; you can see the order by reading the __mro__ property of the Both class:

class Something():
    pass

class SomethingElse():
    pass

class Both(Something, SomethingElse):
    pass

print(Both.__mro__)

Which will tell you the order:

(<class '__main__.Both'>, <class '__main__.Something'>, <class '__main__.SomethingElse'>, <class 'object'>)

And explain why you're ending up calling object.__init__ with your second call to super(...).__init__(...).