Используйте метакласс только для подклассовPython

Программы на Python
Ответить
Anonymous
 Используйте метакласс только для подклассов

Сообщение Anonymous »

Обновление Python 3.6:
Во многих случаях (включая пример, который я использую для этого вопроса ниже) переопределение __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
В определении EnumMeta.__new__ видно, что мне пришлось исключить get_by_value из обработки метакласса. Я часто сталкиваюсь с этой проблемой, когда хочу каким-либо образом обработать члены определения класса с помощью метакласса.
Какой подход является предпочтительным для исключения базового класса ( в примере) от обработки метаклассом (

Код: Выделить всё

EnumMeta
в примере) при использовании метакласса для всех подклассов базового класса?
Я не думаю, что исключение всех членов базового класса при обработке членов подкласс является предпочтительным подходом. Меня не волнует значение типа (Enum). Это может быть EnumMeta или тип.

Подробнее здесь: https://stackoverflow.com/questions/212 ... subclasses
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»