Я реализую перечисление, используя базовый класс, который определяет множество методов. Фактические перечисления являются подклассами этого, без дополнительных методов или атрибутов. (Каждый подкласс заполняется своими собственными значениями с использованием конструктора, определенного в базовом классе).
Я использую реестр (атрибут класса, в котором хранятся все экземпляры этого класса). В идеале я бы хотел избежать определения его в каждом подклассе. К сожалению, если я определю его в базовом классе, все подклассы будут иметь общий реестр.
Какой хороший подход здесь?
Ниже приведена реализация, если она помогает (она основана на комментарии @jchl в классе перечисления python для целей ORM ).
class IterRegistry(type):
def __iter__(cls):
return iter(cls._registry.values())
class EnumType(metaclass = IterRegistry):
_registry = {}
_frozen = False
def __init__(self, token):
if hasattr(self, 'token'):
return
self.token = token
self.id = len(type(self)._registry)
type(self)._registry[token] = self
def __new__(cls, token):
if token in cls._registry:
return cls._registry[token]
else:
if cls._frozen:
raise TypeError('No more instances allowed')
else:
return object.__new__(cls)
@classmethod
def freeze(cls):
cls._frozen = True
def __repr__(self):
return self.token
@classmethod
def instance(cls, token):
return cls._registry[token]
class Enum1(EnumType): pass
Enum1('a')
Enum1('b')
for i in Enum1:
print(i)
# not going to work properly because _registry is shared
class Enum2(EnumType): pass