[英]Python class design with metaclass
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
.我有一个类设计,其中从某个
Parent
类继承的Children
类只是在某些parameters
有所不同,但Parent
类包含所有方法,这些方法使用作为Children
上的类变量提供的parameters
。 So, in other words, each of my Child
classes is fully described by the list of parameters
and the inheritance of the Parent
class.因此,换句话说,我的每个
Child
类都由parameters
列表和Parent
类的继承完全描述。
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.我的实际类有点不同 - 我在
Parent
类上有越来越复杂的方法以及不同种类的参数 - ,但这是设计原则的最小示例。
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.由于
Parent
类依赖于它的Children
来拥有类变量parameters
,我想,我可能想在每个Child
类上强制存在类变量。 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).但另一方面,术语“元类”听起来很适合我的结构,因为
Parent
确实看起来很像在某种意义上可以称为“元类”的东西(从技术上讲,不是就技术术语而言元类在 OOP 中使用,但就以下方面而言:它完全描述了子类的行为)。
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?我应该使用元类来强制
parameters
的存在,还是有更好的方法? Or should I just resign to enforce the existence of the parameters
class variable on the Children classes in the first place?或者我应该辞职以首先强制子类上的
parameters
类变量的存在?
If using python3.6 or above, you can accomplish this using __init_subclass__
which I personally reason better with than a metaclass.如果使用 python3.6 或更高版本,您可以使用
__init_subclass__
完成此操作,我个人认为它比元类更好。
An example of __init_subclass__
based on the usecase described:基于所描述用例的
__init_subclass__
示例:
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):这会导致在创建
BadChild
类时(而不是在实例化时) TypeError
异常:
TypeError: Subclass of <class '__main__.BadChild'> does not have a parameters class attribute
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.