在 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]
创建这种枚举类型的示例:
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
在EnumMeta.__new__
的定义中,您可以看到我必须从元类的处理中排除get_by_value
。当我想使用元类以某种方式处理类定义的成员时,我经常遇到这个问题。
在对基类的所有子类使用元类时,排除基类(示例中的Enum
)与元类(示例中为EnumMeta
)处理的首选方法是什么?
我不认为在处理子类成员时排除基类的所有成员是首选方法。我不关心type(Enum)
的价值。它可以是EnumMeta
或type
。
答案 0 :(得分:7)
您的“父级”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