使用元类的 Python 类设计

标签 python oop metaclass

我有一个类设计,其中从某个Parent类继承的Children类只是在某些参数上有所不同,但是父类包含所有方法,这些方法使用作为子类变量提供的参数。因此,换句话说,我的每个 Child 类都由 参数 列表和 Parent 类的继承完整描述。 p>

那么,假设我有以下类(class):

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)

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

由于Parent类依赖其Children来拥有类变量parameters,我想,我可能想要强制存在每个Child 类上的类变量。我读到我通过使用元类来实现这一点。但我还了解到大多数开发人员不需要使用元类,如果有疑问,您可能不需要它们。我以前从未使用过元类,因此我不确定是否应该使用它们,因此根据提到的规则,我可能不需要元类。但另一方面,术语“元类”听起来很适合我的结构,因为 Parent 确实看起来很像某种意义上可以称为“元类”的东西(从技术上讲,不是在就 OOP 中使用术语技术元类的方式而言,但就以下方面而言:它完全描述了子类的行为)。

所以,我想知道:是否有不同(更好)的类设计来反射(reflect)我的结构?我应该使用元类来强制参数的存在,还是有更好的方法?或者我应该辞职以强制 Children 类中存在 parameters 类变量?

最佳答案

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

基于所描述的用例的__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 类时(而不是在实例化它时)引发 TypeError 异常:

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

关于使用元类的 Python 类设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55320487/

相关文章:

methods - 向元类添加方法

python - 需要 Django 用户输入步骤

python - 使用 python 确定时间戳是否在夏令时

python - Shapely的 `almost_equals`函数如何处理起点和错误?

perl - 如何在 Perl 中取消祝福对象?

c++ - 是否可以让指针指向第一个指针指向的变量?

Qt ENUMS - setProperty 隐式转换

python - 如何继承 ABCMeta

php - 如何创建 pyserial 网络服务?

java - 抽象工厂模式依赖于对象组合?