mauscope
mauscope

Reputation: 318

Passing arguments to the right inherited class with super()

Let assume that a class inherits 2 classes: one takes 1 argument, the other none. How do I ensure that the argument is passed to the class accepting the argument independently of the order of the subclasses?

Specifically, I have problems with this example:

class Generic(object):
    def __init__(self,data): 
        self.data=data
    def do_data(self):
        print(self.data)
class Generic2(object):
    def __init__(self):
        pass
    def no_data(self):
        print("No_data")
class MyClass(Generic2,Generic):
    def __init__(self,data):
        self.data=data
        super().__init__(data)
A=MyClass("A")

Returns a TypeError due to init arguments.

The error is simply corrected by using:

  ...
 class MyClass(Generic,Generic2):
  ...

I assume that super() uses the MRO to decide which class to initialise.

The question is: in Python3, how can I ensure that the arguments are sent to the correct subclass independently of the order of my subclasses?

(be gentle... I have very flaky knowledge of anything OO!)

Upvotes: 0

Views: 1060

Answers (2)

Lennart Regebro
Lennart Regebro

Reputation: 172219

A bit of an extension and comment that is too long for a comment:

When you know exactly how your class hierarchy looks you can call the method you want to call directly. super() is necessary when you aren't sure how the class hierarchy looks. This is the case when you make a library, for example. You don't know how people will use that library and which of your baseclasses they are going to use. So there you need to make sure that the interface for all classes are the same, and that all of them call super().

But as soon as the interfaces of the classes aren't the same, super() stops becoming useful, partly because you no longer can call the classes in an arbitrary order anyway. You now must initialize them in a specific order, and then you must make that order explicit.

Upvotes: 1

dav1d
dav1d

Reputation: 6055

Related: https://fuhm.net/super-harmful/.

Just use the class you wanna initialize directly:

class MyClass(Generic2, Generic):
    def __init__(self, data):
        Generic.__init__(data)
        self.data = data

Upvotes: 3

Related Questions