0

Assume I have 4 classes class ModelA, class ModelB, class ModelC class ModelD.

I have another class LongModel. I want to choose from the above 4 classes as the BaseClass for the class LongModel, based on model_name. What's the right way to do it. As of now, I am doing the following:

def get_long_model(model_name):
   if model_name == 'A':
       base_class = Model_A
   if model_name == 'B':
       base_class = Model_B
   if model_name == 'C':
       base_class = Model_C
   if model_name == 'D':
       base_class = Model_D
   
   return LongModel(base_class)

I really don't want to use a function. Can we do this over the LongModel itself?

For eg:

class LongModel():
    def __init__(self, model_name):
        if model_name == 'A':
             # Assign base class for LongModel

or some neat way using class or anything.

If I use composition then,

class LongModel():
    def __init__(self, model):
        self.model = model

long_model = LongModel(ModelA)

Then, assume ModelA has some attributes, which I want to use inside LongModel say the name, I have to add self.name = model.name, for one or 2 attributes its okay. But for all/most attributes isn't it difficult?

Sarath R Nair
  • 485
  • 2
  • 6
  • 18
  • 5
    I would argue this is a good time for [composition over inheritence](https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance) meaning instead of swapping out the base class (inheritance) instead you should swap out a member variable of your class – Cory Kramer Jun 14 '21 at 13:52
  • Can you give me a basic layout example. – Sarath R Nair Jun 14 '21 at 13:56
  • Obviously inheritance is done in `class LongModel(BaseClass):`, so no, you can't do what you want. Use composition. – Matthieu Brucher Jun 14 '21 at 13:56
  • There’s only one `LongModel` *class object*. You can’t dynamically switch out its base, since that changes it for every instance of `LongModel`. That’s simply not how that relationship works. – deceze Jun 14 '21 at 13:57
  • If I use composition. I have to pass the model as an attribute right. But, then all attributes of the model have to defined explicitly in the child class right. – Sarath R Nair Jun 14 '21 at 14:01
  • 1
    @SarathRNair the shared attributes can be defined in the outer class, while the specific attributes which are not shared by all can be defined in the inner class. If there are attributes which are only shared with some of the classes, consider using an intermediate class for those using either inheritance or composition as appropriate. – Will Da Silva Jun 14 '21 at 14:05

1 Answers1

1

What you've described (using a function to select the class) is akin to using a factory, but has the disadvantage of remaking the classes each time it is run. This would mess with type checking/comparison. In general you should only create each class object exactly once.

If you'd like to control this behaviour from inside the LongModel class, you can do so by overriding its __new__ method as described here: https://stackoverflow.com/a/10357472/5946921

I do not recommend you do this, however, as it is most likely bad design. You should definitely generate all of your classes upfront, and then re-use those class objects, to prevent issues around type checking/comparison later on. Additionally, consider using composition instead of inheritance for this.

Will Da Silva
  • 6,386
  • 2
  • 27
  • 52
  • The reason I thought this way is because if I define ```class LongModelA```, ```class LongModelB``` so on, isn't it redundant in nature.? In the future, if I have more models like Model N, I have to keep re-writing them. – Sarath R Nair Jun 14 '21 at 14:01
  • You can generate your classes dynamically using `type`, among other methods. The important thing is that you do it exactly once for each logical type. See: https://stackoverflow.com/questions/15247075/ – Will Da Silva Jun 14 '21 at 14:03
  • I went with composition – Sarath R Nair Jun 15 '21 at 01:46