仅为子类使用元类

Feu*_*mel 6 python metaclass python-3.x

Python 3.2或更高版本中是否有一种方法可以定义一个类,其子类应该使用特定的元类创建而不使用该元类创建类本身?

举例来说明我的意思:假设我想创建一个Enum类,其子类可用于定义枚举类型.枚举类型将具有固定数量的实例,每个实例具有不同int(或其他)值.枚举类型将通过创建子类Enum并将值赋给该类的属性来声明.通过元类Enum,这些属性的值将被新类的实例替换.

Enum班还可以定义可以在其子类或它们的情况下使用一些类或实例方法或成员.

class EnumMeta(type):
    def __new__(mcs, what, bases, dict):
        cls = super().__new__(mcs, what, bases, { })

        cls._instances_by_value = { }

        for k, v in dict.items():
            if k.startswith('__') or k == 'get_by_value':
                setattr(cls, k, v)
            else:
                instance = cls(k, v)

                setattr(cls, k, instance)
                cls._instances_by_value[v] = instance

        return cls


class Enum(metaclass = EnumMeta):
    def __init__(self, name, value):
        self.name = name
        self.value = value

    def __repr__(self):
        return '{}.{}'.format(type(self).__name__, self.name)

    @classmethod
    def get_by_value(cls, value):
        return cls._instances_by_value[value]
Run Code Online (Sandbox Code Playgroud)

创建这种枚举类型的示例:

class Boolean(Enum):
    true = 0
    false = 1
    file_not_found = 2

print(Boolean.true) # Prints Boolean.true
print(Boolean.get_by_value(1)) # Prints Boolean.false
Run Code Online (Sandbox Code Playgroud)

在定义中EnumMeta.__new__,您可以看到我必须get_by_value从元类的处理中排除.当我想使用元类以某种方式处理类定义的成员时,我经常遇到这个问题.

在对基类的所有子类使用元类时,Enum从元类(EnumMeta在示例中)处理基类(在示例中)中排除基类的首选方法是什么?

我不认为在处理子类成员时排除基类的所有成员是首选方法.我不在乎的价值type(Enum).它可以是EnumMetatype.

Mar*_*ers 8

你的'父母' Enum将没有任何基础,只有派生的类Enum将具有非空bases元组.使用它可以很容易地提前纾困,通过常规__new__调用创建基类:

class EnumMeta(type):
    def __new__(mcs, what, bases, dict):
        if not bases:
            # Enum itself
            return super().__new__(mcs, what, bases, dict)

        # Process subclass creation
Run Code Online (Sandbox Code Playgroud)

  • 这确实是一个非常干净的解决方案。您将如何处理`Enum` _does_具有基类的情况?检查“ base”字典是否完全匹配? (2认同)