0

Assume you have two parent classes with the same interface in some module parents.py

class Mother:
    def __init__(self):
         print("mother")

class Father:
    def __init__(self):
         print("father")

and you want to use a child class, which can operate on both classes, such as

import parents

class Child:
    def __init__(self,parent_choice):
        parents.parent_choice.__init__()

Is it possible to create such an child object choosing the right parent as variable? something like

import child

son_of_your_mother = Child(Mother)

The best approach would be having separate modules (.py files) for each of the parents (not as shown in my example). Any other approach to the issue is welcome, as long as it keeps the two parent classes separate (divorce is often good for the kids).

Francesco
  • 393
  • 1
  • 3
  • 8
  • The line `parents.parent_choice.__init__()` gives an error. Please do not write code that obviously does not work. – albar Feb 22 '18 at 14:59
  • Sorry not that obvious to me. Normally I would do super().__init__(**args). How is that not equivalent? – Francesco Feb 22 '18 at 15:01
  • Not that obvious ??? Simply test your code ! – albar Feb 22 '18 at 15:02
  • the problem is at son_of_your_mother = child(mother), where mother should be an instance of mother, not at the line you mentioned. And I did not instantiate it because the goal would be to instantiate an object while doing this, but inherit the class attributes. Of course the code doesn't work the way I put it, otherwise I would have no question – Francesco Feb 22 '18 at 15:09

3 Answers3

1

Define mother and father as child attributes, keep the two as references to the mother and father object instances (has-a relationship)

class Mother:
    ...

class Father:
    ...

class Child:
    def __init__(self, mother, father):
        self.mother = mother
        self.father = father
        ...
    ...
    # use whatever attributes/methods you want from mother or father with
    # self.mother.somethod() or self.father.someattribute


mother1 = Mother() # create real objects from your classes
father1 = Father()
child1 = Child(mother1, father1) # pass them to the child `__init__`

Where you keep the Mother and Father classes is irrelevant. You might keep them in the same file or make a family.py module and then

from family import Mother, Father

class Child:
...

defining your child in the current script.

Edit:

As per your comments you would need to inherit the Child class from some Parent class, from which you also inherit both Mother and Father classes. That would inherit the methods and attributes but would also state that a Child is also a Parent, which he isn't. But they are all Persons, so you can create a Person class with common attributes and methods, extend it with a Mother and Father class both inheriting from Person, and then alter the child class __init__ to receive a list of parents. You mantain a container-like has-a relationship, but now a child can have many parents. Maybe add a method add_parent to append new parents to that list in self.parents. If creating methods in Child just to delegate (call) the corresponding methods in the parents becomes labourious, then you might consider changing the Child class to inherit from Person class too, getting all the common Parents machinery. You'll need to adapt a bit the code in those scenarios, but I think you get it.

progmatico
  • 4,714
  • 1
  • 16
  • 27
  • Thank you, this partially solves the problem (adding maybe a conditional statement, if it's not desired to create both objects). The problem with this, which is more structural than practical I guess, is that child does not inherit the parents class attributes, but sort of contains them. For now I will use this solution, but ideally I would want to call, say function foo from mother as child.foo(). – Francesco Feb 22 '18 at 15:13
  • Also, with this solutions the possible classes that child can take must be hardcoded in child itself, whereas it would be useful to be able to add extra parents, without modifying the child class – Francesco Feb 22 '18 at 15:17
0

I found a very similar question: Pass a parent class as an argument?

The solution is to define a function that wraps the class. In this case would be something like

import parents

def Child(parent):

    class Child(parent):
         # stuff

    return Child

and to create instances

import child

c = Child(Mother)(**args)
Francesco
  • 393
  • 1
  • 3
  • 8
0

You could pass a string to Child then use getattr to create a parent object.

import parents

class Child:
    def __init__(self,parent_choice):
        self.parent = getattr(parents, parent_choice)()

Then you would use it like this

son_of_your_mother = Child('Mother')
wwii
  • 23,232
  • 7
  • 37
  • 77