Reputation: 6154
I have a class design where the Children
classes inheriting from a certain Parent
class just differ in some parameters
, but the Parent
class contains all methods, which are using the parameters
provided as class variables on the Children
. So, in other words, each of my Child
classes is fully described by the list of parameters
and the inheritance of the Parent
class.
So, let's say, I have the following classes:
class Parent():
def __init__(self, **kwargs):
for param in self.__class__.parameters:
self.setattr(param, kwargs.get(param))
def compare(self, other):
for param in self.__class__.parameters:
if self.getattr(param) != other.getattr(param):
return False
return True
class ChildA(Parent):
parameters = ["length", "height", "width"]
def __init__(self, **kwargs):
super().__init__(**kwargs)
class ChildB(Parent):
parameters = ["color", "taste"]
def __init__(self, **kwargs):
super().__init__(**kwargs)
My actual classes are a bit different - I have more and more complex methods on the Parent
class and also different kinds of parameters - , but this is sort of a minimum example of the design principle.
Since Parent
class is relying on its Children
to have the class variable parameters
, I thought, I might want to enforce the existence of the class variable on each Child
class. I have read that I achieve this by using a metaclass. But I have also read that most developers do not need to use metaclasses, and if in doubt, you probably don't need them. I have never worked with metaclasses before, and so I am in doubt whether I should use them, and so by that rule mentioned, I probably do not need a metaclass. But on the other hand, the term "metaclass" just sounds like a good match to my structure, since Parent
really looks like something which could well be called "metaclass" in some sense (technically, not in terms of the way the terminus technicus metaclass is used in OOP, but in terms of: it is fully describing the behaviour of the children classes).
So, I wonder: Is there a different (better) design of classes to reflect my structure? Should I use a metaclass to enforce the existence of the parameters
, or is there a better way to do so? Or should I just resign to enforce the existence of the parameters
class variable on the Children classes in the first place?
Upvotes: 1
Views: 129
Reputation: 5805
If using python3.6 or above, you can accomplish this using __init_subclass__
which I personally reason better with than a metaclass.
An example of __init_subclass__
based on the usecase described:
class Parent:
def __init_subclass__(cls):
if not hasattr(cls, 'parameters'):
raise TypeError(f'Subclass of {cls} does not have a parameters class attribute')
def __init__(self, **kwargs):
for param in self.__class__.parameters:
self.setattr(param, kwargs.get(param))
def compare(self, other):
for param in self.__class__.parameters:
if self.getattr(param) != other.getattr(param):
return False
return True
class GoodChild(Parent):
parameters = ['length', 'height', 'width']
class BadChild(Parent):
pass
Which results in raising a TypeError
exception when the BadChild
class is created (not when it is instantiated):
TypeError: Subclass of <class '__main__.BadChild'> does not have a parameters class attribute
Upvotes: 1