Python class 元设计class

Python class design with metaclass

我有一个 class 设计,其中 Children class 继承自某个 Parent class 只是在一些 parameters 上有所不同,但 Parent class 包含所有方法,这些方法使用 Children 上作为 class 变量提供的 parameters。所以,换句话说,我的每个 Child classes 都完全由 parameters 的列表和 Parent class 的继承描述。

那么,假设我有以下 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)

我实际的 classes 有点不同 - 我在 Parent class 上有越来越复杂的方法以及不同种类的参数 - 但这有点设计原则的最小示例。

因为Parent class 依赖于它的Children 有class 变量parameters,我想,我可能想要强制存在每个 Child class 上的 class 变量。我读过我通过使用 metaclass 来实现这一点。但我也了解到大多数开发人员不需要使用 metaclasses,如果有疑问,你可能不需要它们。我以前从未使用过 metaclasses,所以我怀疑我是否应该使用它们,所以根据提到的规则,我可能不需要 metaclass。但另一方面,术语 "metaclass" 听起来很适合我的结构,因为 Parent 确实看起来很像某种意义上可以称为 "metaclass" 的东西(从技术上讲,不是就在 OOP 中使用 terminus technicus metaclass 的方式而言,但就以下方面而言:它完全描述了 children [=46] 的行为=]es).

所以,我想知道:classes 是否有不同(更好)的设计来反映我的结构?我应该使用 metaclass 来强制 parameters 的存在,还是有更好的方法?或者我应该首先辞职以在 Children classes 上强制存在 parameters class 变量?

如果使用 python3.6 或更高版本,您可以使用 __init_subclass__ 完成此操作,我个人认为它比 metaclass.

更好

基于所述用例的 __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

这会导致在创建 BadChild class 时引发 TypeError 异常(而不是在实例化时):

TypeError: Subclass of <class '__main__.BadChild'> does not have a parameters class attribute