创建一个抽象的Enum类

发布于 2021-01-29 17:30:37

我正在尝试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冲突,切换到失败。

我想以某种方式获得这样的功能:

@abstractclassmethod
@classmethod
    def base(cls):
        pass

有可能实现这一目标吗?

关注者
0
被浏览
165
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    这是使用ABCMeta和EnumMeta来调整对抽象枚举类问题的接受答案的方法,以创建所需的抽象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'
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看