我正在尝试Flag使用抽象方法创建一个抽象枚举(实际上)。我的最终目标是能够根据我定义的基本枚举创建复合枚举的字符串表示形式。我可以在不使类抽象的情况下获得此功能。
Flag
这是基本Flag类和示例实现:
from enum import auto, Flag class TranslateableFlag(Flag): @classmethod def base(cls): pass def translate(self): base = self.base() if self in base: return base[self] else: ret = [] for basic in base: if basic in self: ret.append(base[basic]) return " | ".join(ret) class Students(TranslateableFlag): ALICE = auto() BOB = auto() CHARLIE = auto() ALL = ALICE | BOB | CHARLIE @classmethod def base(cls): return {Students.ALICE: "Alice", Students.BOB: "Bob", Students.CHARLIE: "Charlie"}
一个示例用法是:
((Students.ALICE | Students.BOB).translate()) [Out]: 'Alice | Bob'
TranslateableFlag(Flag,ABC)由于MetaClass冲突,切换到失败。
TranslateableFlag(Flag,ABC)
我想以某种方式获得这样的功能:
@abstractclassmethod @classmethod def base(cls): pass
有可能实现这一目标吗?
这是使用ABCMeta和EnumMeta来调整对抽象枚举类问题的接受答案的方法,以创建所需的抽象Enum类:
Enum
from abc import abstractmethod, ABC, ABCMeta from enum import auto, Flag, EnumMeta class ABCEnumMeta(ABCMeta, EnumMeta): def __new__(mcls, *args, **kw): abstract_enum_cls = super().__new__(mcls, *args, **kw) try: # Handle existence of undefined abstract methods. absmethods = list(abstract_enum_cls.__abstractmethods__) absmethods_str = ', '.join(f'{method!r}' for method in absmethods) plural = 's' if len(absmethods) > 1 else '' raise TypeError( f"cannot instantiate abstract class {abstract_enum_cls.__name__!r}" f" with abstract method{plural} {absmethods_str}") except AttributeError: pass return abstract_enum_cls class TranslateableFlag(Flag, metaclass=ABCEnumMeta): @classmethod @abstractmethod def base(cls): pass def translate(self): base = self.base() if self in base: return base[self] else: ret = [] for basic in base: if basic in self: ret.append(base[basic]) return " | ".join(ret) class Students1(TranslateableFlag): ALICE = auto() BOB = auto() CHARLIE = auto() ALL = ALICE | BOB | CHARLIE @classmethod def base(cls): return {Students1.ALICE: "Alice", Students1.BOB: "Bob", Students1.CHARLIE: "Charlie"} class Students2(TranslateableFlag): ALICE = auto() BOB = auto() CHARLIE = auto() ALL = ALICE | BOB | CHARLIE # Abstract method not defined - should raise TypeError. # @classmethod # def base(cls): # ...
结果:
Traceback (most recent call last): ... TypeError: cannot instantiate abstract class 'TranslateableFlag' with abstract method 'base'