当Enum成员不存在时返回默认成员

问题描述 投票:0回答:2

我有一个枚举,当其中不存在成员时,我希望返回默认成员。例如:

class MyEnum(enum.Enum):
    A = 12
    B = 24
    CUSTOM = 1


print(MyEnum.UNKNOWN) # Should print MyEnum.CUSTOM

我知道我可以像这样使用元类:

class MyMeta(enum.EnumMeta):
    def __getitem__(cls, name):
        try:
            return super().__getitem__(name)
        except KeyError as error:
            return cls.CUSTOM

class MyEnum(enum.Enum,metaclass=MyMeta):
    ...

但这似乎只有在我使用

MyEnum['UNKNOWN']
访问枚举时才有效。当成员不存在时,是否有一种方法可以涵盖访问枚举成员的两种方法?

python enums
2个回答
4
投票

__getattr__
的定义添加到元类:

class MyMeta(enum.EnumMeta):
    def __getitem__(cls, name):
        try:
            return super().__getitem__(name)
        except KeyError as error:
            return cls.CUSTOM
    
    def __getattr__(cls, name):
        try:
            return super().__getattr__(name)
        except AttributeError as error:
            return cls.CUSTOM

然后,你的代码将输出:

MyEnum.CUSTOM

0
投票

编译@BrokenBenchmark答案,和这个答案,以及一些知识,让我们将默认枚举成员设置为参数:

class EnumWithDefaultMeta(enum.EnumMeta):

    @classmethod
    def __prepare__(metacls, name, bases, **kwargs):
        return super().__prepare__(name, bases)

    def __new__(metacls, name, bases, namespace, **kwargs):
        newclass = super().__new__(metacls, name, bases, namespace)
        newclass._missing_ = classmethod(metacls._missing_)
        return newclass

    def __init__(cls, name, bases, namespace, default='UNKNOWN'):
        cls.default = default
        super().__init__(name, bases, namespace)

    def __getitem__(cls, name):
        try:
            return super().__getitem__(name)
        except KeyError:
            return super().__getitem__(cls.default)

    def __getattr__(cls, name):
        try:
            # noinspection PyUnresolvedReferences
            return super().__getattr__(name)
        except AttributeError:
            # noinspection PyUnresolvedReferences
            return super().__getattr__(cls.default)

    def _missing_(cls, _value):
        return super().__getitem__(cls.default)

class MyEnum(enum.Enum, metaclass=EnumWithDefaultMeta, default='CUSTOM'):
    A = 12
    B = 24
    CUSTOM = 1

输出:

MyEnum(123)
>>> <MyEnum.CUSTOM: 1>
MyEnum.Test
>>> <MyEnum.CUSTOM: 1>
MyEnum['Test']
>>> <MyEnum.CUSTOM: 1>
© www.soinside.com 2019 - 2024. All rights reserved.