0

Assuming this:

class Father():
    def __init__(self,fathername):
        self.papa = f"The father is {fathername.upper()}"

class Mother():
    # Mother class is COMPLETELY DIFFERENT AS Father.
    # The important thing is that they both built an attribute each.
    def __init__(self,mothername):
        self.mama = f"the mother is {mothername.lower()}"
        
class Child3(Father,Mother):
    def __init__(self,name,fathername,mothername):
        Father.__init__(self,fathername)
        Mother.__init__(self,mothername)
        self.name=name

both of the following works:

c = Child3('Noa',fathername='J',mothername='M')
c = Child3('Noa','J','M')

So far so good. But assuming I want to inherit from several classes (not multiple nesting inheritances but just one class inheriting from several ones that don't inherit from anything else) How can I use super() to initialise the parent classes?

The following does not work:

class Child4(Father,Mother):
    def __init__(self,name,fathername,mothername):
        super().__init__(self,fathername=fathername,mothername=mothername)
        self.name=name

TypeError: init() got multiple values for argument 'fathername'

Some previous consultations:

  1. How does Python's super() work with multiple inheritance? This is a very complete with very nice answers which I already voted up some time ago. Nevertheless this question is a bit different and not entirely the case I am asking here, i.e. MRO (Method resolution order) is of no importance here. I would like to achieve a way to hard code initialise the parent classes to access all of the attributes. In the mentioned question the answer with the most votes does not have attributes in the parent classes. In the second most voted answer the parent classes DO NOT HAVE ATTRIBUTES neither. Yet in another of the answers there is a very complete explanation of MRO with multi inheritance, which again, is not the point here since there is one one level of inheritance.

  2. In this other question with a lot of positive up votes there is no attributes of the parents classes neither: Calling parent class __init__ with multiple inheritance, what's the right way?

  3. This is the one coming closer, but not implementing a solution with super() Python - Calling __init__ for multiple parent classes actually suggesting going away from inheritance paradigm

  4. This is a close one: calling init for multiple parent classes with super? but I see there there is super() in the parent classes which is counter productive since the aim is not having to modify the parent classes.

In order to understand the use of this example and why I HAVE TO USE inheritance think that the first parent class calls an API and performs a couple of 1000s code NLP process to extract data of the API response. The same goes for the second parent class. Then the child class will try to get insights comparing both further using NLP.

The classes Mother and Father are given. They are not coded by me. I don't have a chance to modify them. They don't depend on any other class.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
JFerro
  • 3,203
  • 7
  • 35
  • 88
  • 1
    I support the advise to reconsider whether multiple inheritance is the best solution here. Inheriting multiple interfaces is okay, but "shopping" for functionality by inheritance is normally a bad design. – Dr. V Apr 03 '21 at 13:07
  • Consider [this](https://stackoverflow.com/questions/30353498/python-multiple-inheritance-call-super-on-all/30354798#30354798) answer. – dawg Apr 03 '21 at 13:47
  • thanks @dawg. It is indeed a very good question/answers. Nevertheless for some reason all those examples DO NOT USE attributes variables. i.e. in my case the first thing I need to do when instantiating the class child is call the attributes of Father and Mother class. Its not about just to call a method of a parent class. Is about using the attributes of the parent classes in the Child. – JFerro Apr 03 '21 at 14:20
  • @Dr.V It does not look that I have other option (as far as I know) to using inheritance when wanting to have all the attributes of the parent classes and make all transparent to the user at Child level. – JFerro Apr 03 '21 at 14:21
  • `super().__init__(self, ...)` is a mistake, because you don't explicitly pass `self` as an argument when calling an instance method. That's why you get the error - Python sees the `self` argument and binds it to the `fathername` parameter, then it sees the `fathername` keyword argument and raises an exception because that parameter already received a value. – kaya3 Apr 03 '21 at 14:53
  • 1
    You've already got the options: your parent classes cooperate correctly (which you can't do because you don't own them); you call them all explicitly (which doesn't scale); or you do something other than inheritance. You might not _like_ the options, but we can't is much about that. – jonrsharpe Apr 03 '21 at 22:50
  • 1
    "Shouting" doesn't help anyone; we need *more context* as to why those answers don't solve your specific problem, because your current explanations don't make sense. From the final paragraph I'm not even sure why you think inheritance is the way to go, it seems that you should be composing over a *list* of those "parent" classes. – jonrsharpe Apr 04 '21 at 07:28
  • @jonrsharpe Your last comment could have been a perfect answer. a) cooperation with parent classes (not possible) b) calling them explicitly (which does not scale) c) something else. I would vote that as answer if you propose it. – JFerro Apr 05 '21 at 10:15
  • @jonrsharpe regarding your last comment I was not shouting, i was begging. But all points to the fact that marking questions as duplicate gives a lot of points. Otherwise is not understandable how people mark a question as duplicate assuming you have to infer a million things from the other questions. – JFerro Apr 05 '21 at 10:18
  • @JFerro no, you don't gain any rep from closing. You can see the list of things that accrue rep on https://stackoverflow.com/help/whats-reputation. – jonrsharpe Apr 05 '21 at 10:27
  • @jonrsharpe if you reopen the question I would post myself a complete answer. I dont know if that is possible – JFerro Apr 07 '21 at 13:12

1 Answers1

0

A child has a mother and a father and would best be designed to have mother and father attributes contained within. I think the following class definitions make more sense for your case:

class Person():
    def __init__(self, name):
        self._name = name

    def get_name(self):
        return self._name

class Child(Person):
    def __init__(self, name, father_name, mother_name):
        super().__init__(name)
        self._father = Person(father_name)
        self._mother = Person(mother_name)

    def get_father_name(self):
        return self._father.get_name()

    def get_mother_name(self):
        return self._mother.get_name()


child = Child('Peter', 'Joseph', 'Mary')
print(child.get_name(), child.get_father_name(), child.get_mother_name())

Prints:

Peter Joseph Mary
Booboo
  • 38,656
  • 3
  • 37
  • 60
  • thanks for your answer @Booboo. Unfortunately this does not fly. Imaging a situation in which the classes Mother and Father are totally independently from each other, coded by two different people. The class Child should further combine the results with other NLP methods to further obtain other results. I don't have the possibility to modify The two parent classes. – JFerro Apr 03 '21 at 14:29
  • 1
    I would agree *given your premise*. But my premise is that whoever coded those original `Mother` and `Father` classes has made a gross error; that's my only point. I don't think you would find your actual situation in a real profession IT department. I would hope not, anyway. These are poorly designed classes unusable for multiple inheritance whose abstractions are rather useless. – Booboo Apr 03 '21 at 14:34
  • 1
    But the main point I was making is that, even if you stick with the *original* class definitions, multiple inheritance should not be used. Instead, you should be using containment. – Booboo Apr 03 '21 at 14:38
  • 1
    @Booboo I think you are reading the class names too literally. I think they are just meant as an example, so this advice is not really helpful. If you want to take it very literally, I could criticise your proposed design by pointing out that in fact not every child has one mother and one father; there are single parents, same-sex parents, and non-binary parents, and some children have no parents. But this is clearly missing the point of the question, which is about multiple inheritance, not software design. – kaya3 Apr 03 '21 at 14:43
  • thanks @Booboo for your insights. Indeed, as I edited now the question the classes Father and Mother are totally different they can't by no means be two instances of a single class. Booboo: we are not talking about a IT department but to find a way to reuse code done by other people who don't actually have a CS degree and use python as side-tool. I am also making this experience that when reading about multi inheritance oftentimes people in SO jump very fast to MRO in complex inheritance chains but less often I see easy solutions. I will nevertheless have a look to "composition" – JFerro Apr 03 '21 at 17:19