Во многих случаях (включая пример, который я использую для этого вопроса ниже) переопределение __init_subclass__() является более простым решением. по сравнению с использованием метакласса. Во всех остальных случаях ответ Мартина Питерса ниже работает хорошо.
Есть ли способ в Python 3.2 или более поздней версии определить класс, подклассы которого должны быть созданы с использованием определенного метакласса, без создания самого класса с использованием этого метакласса?
Пример, демонстрирующий, что я имею в виду: допустим, я хочу создать Enum code> класс, подклассы которого могут использоваться для определения типов перечислений. Тип перечисления будет иметь фиксированное количество экземпляров, каждый из которых имеет отдельное значение 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
Какой подход является предпочтительным для исключения базового класса (
Код: Выделить всё
EnumКод: Выделить всё
EnumMetaЯ не думаю, что исключение всех членов базового класса при обработке членов подкласс является предпочтительным подходом. Меня не волнует значение типа (Enum). Это может быть EnumMeta или тип.
Подробнее здесь: https://stackoverflow.com/questions/212 ... subclasses
Мобильная версия