I'm trying to create an abstract enum (Flag actually) with an abstract method. My final goal is to be able to create a string representation of compound enums, based on the basic enums I defined. I'm able to get this functionality without making the class abstract.
This is the basic Flag class and an example implementation:
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"}
An example usage is:
((Students.ALICE | Students.BOB).translate())
[Out]: 'Alice | Bob'
Switching to TranslateableFlag(Flag, ABC) fails due to MetaClass conflicts. (I didn't understand this post - Abstract Enum Class using ABCMeta and EnumMeta, so I'm not sure if it's answering my question).
I would like get a functionality like this somehow:
@abstractclassmethod
@classmethod
def base(cls):
pass
Is it possible to achieve this?
Here's how to adapt the accepted answer to the question Abstract Enum Class using ABCMeta and EnumMeta to create the kind of abstract Enum class you want:
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)
# Only check abstractions if members were defined.
if abstract_enum_cls._member_map_:
try: # Handle existence of undefined abstract methods.
absmethods = list(abstract_enum_cls.__abstractmethods__)
if absmethods:
missing = ', '.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} {missing}")
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"}
# Abstract method not defined - should raise TypeError.
class Students2(TranslateableFlag):
ALICE = auto()
BOB = auto()
CHARLIE = auto()
ALL = ALICE | BOB | CHARLIE
# @classmethod
# def base(cls):
# ...
Result:
Traceback (most recent call last):
...
TypeError: cannot instantiate abstract class 'Students2' with abstract method 'base'
所有评论(0)