Есть ли способ в 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
.
Это действительно очень чистое решение. Как бы вы справились с ситуацией, когда «Enum' _does_ имеют базовые классы? Проверить точное соответствие «основания»? – Feuermurmel
Да, проверка на точный матч тоже сработает. В конце концов, это то, что мы делаем здесь. –