Python枚举:不区分大小写的构造函数

Hep*_*tus 5 python enums python-2.7

我有一个简单的Python2.7枚举:

from enum import Enum

class Label(enum):
    RedApple = 1
    GreenApple = 2
Run Code Online (Sandbox Code Playgroud)

我希望能够使用不区分大小写的键创建枚举对象:

fruitname = "redapple"
a = Label[fruitname]
Run Code Online (Sandbox Code Playgroud)

我试过创建一个__init__方法:

def __init__(self, key):
    super(Label, self).__init__()
    pass # do comparison here
Run Code Online (Sandbox Code Playgroud)

但一直遇到错误:

super(Label, self).__init__()
NameError: global name 'Label' is not defined
Run Code Online (Sandbox Code Playgroud)

我想做一个比较key.lower().strip().
这甚至可能吗?

Eth*_*man 9

在Python 3.6和1 2(与2.7和3.0+兼容)中添加了一种新方法:2.aenum 2.0_missing_

ValueError引发此方法之前调用此方法,以使自定义代码有机会尝试按值查找枚举成员.不幸的是,这使得它不适合您的用例 - 按名称查找.

幸运的是,aenum有额外的选项来定义一个_missing_name_方法3,当名称查找失败时将调用该方法.

您上面的代码应如下所示:

from aenum import Enum

class Label(Enum):

    RedApple = 1
    GreenApple = 2

    @classmethod
    def _missing_name_(cls, name):
        for member in cls:
            if member.name.lower() == name.lower():
                return member
Run Code Online (Sandbox Code Playgroud)

在使用中:

>>> Label['redapple']
<Label.RedApple: 1>
Run Code Online (Sandbox Code Playgroud)

如果使用3.6 stdlib卡住(或想要保持兼容),你可以(ab)使用_missing_但是:

  • 你将不得不做Label('redapple')(圆形的parens,而不是方括号),和
  • 你会反对enum的设计('redapple'是名字,而不是价值)

1披露:我是Python stdlibEnum,enum34backportAdvanced Enumeration(aenum) 库的作者.

2 enum34没有这些改进,因为它只是为bug修复而维护.

3 _missing_value_是优选的,aenum因为它更明确地检查它是什么,但它回退到_missing_与stdlib的兼容性.

4 aenum v2.0.2有一个错误,_missing_如果_missing_name_没有被覆盖,则会为值和名称调用- 这在v2.0.3 +中得到修复.


小智 8

枚举缺少函数,可以覆盖该函数以使枚举不区分大小写。 \n根据文档\n https://docs.python.org/3.11/howto/enum.html \n缺少\xe2\x80\x93 使用的查找函数当没有找到值时;可能会被覆盖

\n

例子

\n
class Status(enum.Enum):\n    @classmethod\n    def _missing_(cls, value):\n        for member in cls:\n            if member.value == value.upper():\n                return member\n    SUCCESS = \'SUCCESS\'\n    FAILURE = \'FAILURE\'\n\nprint(Status(\'success\'))\n
Run Code Online (Sandbox Code Playgroud)\n

输出

\n
Status.SUCCESS\n
Run Code Online (Sandbox Code Playgroud)\n


Mad*_*ist 7

不是 100% 确定这会在 Python 2.7 中工作,但我想出了一个简单的方法来让它完全按照 Python 3.6+ 的要求工作。

这个想法是由类使用方括号完成名称的查找,这意味着它使用__getitem__元类。因此,您可以创建一个实现不区分大小写搜索的简单元类。由于它将扩展现有的EnumMeta,它将与现有的枚举完全兼容:

class CaseInsensitiveEnumMeta(EnumMeta):
    def __getitem__(self, item):
        if isinstance(item, str):
            item = item.upper()
        return super().__getitem__(item)
Run Code Online (Sandbox Code Playgroud)

这假定您的枚举都是大写的。使用它非常简单:

class Label(Enum, metaclass=CaseInsensitiveEnumMeta):
    REDAPPLE = 1
    GREENAPPLE = 2
Run Code Online (Sandbox Code Playgroud)

我不确定Enum在这种情况下你甚至需要。这里的问题是你的枚举必须全部大写才能工作。如果您想进行真正不敏感的搜索,您必须确保所有的键__members__都正确地折叠起来。

与此同时,你可以做

>>> Label['GreenApple']
Label.GREENAPPLE
Run Code Online (Sandbox Code Playgroud)