我有一个常量Enum类,看起来像这样:
class Animals(Enum):
Dog= 'dog'
Cat= 'cat'
Chicken = 'chicken'
Horse = 'horse'
我需要找到一个简单而有效的方法来查找枚举成员之一的索引。所以我想出了以下的联机:
list(Animals).index(Animals.Chicken)
输出:
2
问题是,解析到一个列表并再次搜索它是不够有效的,我不能改变常数。感觉应该有一个简单的解决方案,我错过了。
您有几个选择:
- 使用索引值作为
Enum
或IntEnum
的值
class Animals(Enum):
Dog= 0
Cat= 1
Chicken = 2
Horse = 3
Animals.Chicken.value #returns 2
- 如果你想保持文字描述太,然后子类
Enum
,并添加所需的属性(见行星的例子在文档):
class Animals(Enum):
Dog = ('dog',0)
Cat = ('cat',1)
Chicken = ('chicken',2)
Horse = ('horse',3)
def __init__(self, textval, idx):
self.textval = textval
self.idx = idx
Animals.Chicken.value #returns ('chicken', 2)
Animals.Chicken.textval #returns 'chicken'
Animals.Chicken.idx #returns 2
由于Enum
成员名不以数字开头,您可以简单地使Enum
子类的_member_map_
属性(存储成员名到值映射的字典)也存储索引数到值映射。
这可以通过将Enum
的元类EnumMeta
子类化,并在原始__new__
方法返回的类对象中为_member_map_
属性的所有对应值添加索引作为新键来完成:
from enum import Enum, EnumMeta
class IndexableEnumType(EnumMeta):
def __new__(metacls, cls, bases, classdict, **kwargs):
enum_class = super().__new__(metacls, cls, bases, classdict, **kwargs)
for i, v in enumerate(list(enum_class._member_map_.values())):
enum_class._member_map_[i] = v
return enum_class
:
class Animals(Enum, metaclass=IndexableEnumType):
Dog= 'dog'
Cat= 'cat'
Chicken = 'chicken'
Horse = 'horse'
print(Animals[2])
print(Animals['Chicken'])
print(Animals.Chicken)
将输出:
Animals.Chicken
Animals.Chicken
Animals.Chicken
由于字典查找的平均时间复杂度为0 (1),因此这比当前调用list.index
的解决方案要有效得多,后者的时间复杂度为0 (n)。
演示:https://replit.com/@blhsing/AdventurousVapidCollaborativesoftware