Python中的自定义枚举创建

Custom enum creation in Python

本问题已经有最佳答案,请猛点这里访问。

我可以很容易地创建一个类

1
2
3
4
class MyEnum(enum.Enum):
  BOB ="bob"
  RALPH ="ralph"
  ETC ="etc"

然后我可以通过枚举值分配变量:

a = MyEnum('bob')

但是——我想通过一些可能是正确值的东西来分配变量。也就是说,我想这样做

1
2
3
a = MyEnum('bob')
b = MyEnum('Bob')
c = MyEnum('BOB')

让它们都工作,并且都映射到相同的枚举值。

有没有一种方法可以在不使用工厂方法的情况下做到这一点?我目前已经定义了一个create方法,所以a = MyEnum.create('Bob')可以工作,但我希望事情是无缝的。


您要查找的对象称为_missing_,从python3.6起在stdlib中提供,从2.0起在aenum1中提供。

1
2
3
4
5
6
7
8
9
10
11
class MyEnum(Enum):

    BOB ="bob"
    RALPH ="ralph"
    ETC ="etc"

    @classmethod
    def _missing_(cls, value):
        for member in cls:
            if member.value == value.lower():
                return member

如果_missing_未能返回MyEnum成员,那么EnumMeta将引发异常(因此_missing_不必担心该部分)2。

1公开:我是python stdlib Enumenum34backport和advanced enumeration(aenum库的作者。

2谢谢你,阿兰·费伊,把这件事提出来。


这可以通过将EnumMeta子类化来实现,后者是负责定义MyEnum('Bob')调用的__call__方法的元类。

1
2
3
4
5
6
7
8
9
10
11
import enum

class CaseInsensitiveEnum(enum.EnumMeta):
    def __call__(self, string):
        string = string.lower()  # convert the string to lowercase
        return super().__call__(string)

class MyEnum(enum.Enum, metaclass=CaseInsensitiveEnum):
  BOB ="bob"
  RALPH ="ralph"
  ETC ="etc"

(请记住,所有枚举值都必须是小写的;即,BOB = 'Bob'将不起作用。)

演示:

1
2
3
4
>>> MyEnum('Bob')
<MyEnum.BOB: 'bob'>
>>> MyEnum('Bob') is MyEnum.BOB
True