Python中的枚举枚举?

Enum of enums in Python?

是否可以在python中使用枚举?例如,我想

1
2
3
4
5
6
7
enumA
    enumB
        elementA
        elementB
    enumC
        elementC
        elementD

我可以把elementA称为enumA.enumB.elementA,或者把elementD称为enumA.enumC.elementD

这有可能吗?如果是这样,怎么办?

编辑:以幼稚的方式实现时:

1
2
3
4
5
6
7
8
from enum import Enum

class EnumA(Enum):
    class EnumB(Enum):
        member = 0

print(EnumA)
print(EnumA.EnumB.member)

它给出:

1
2
3
4
5
<enum 'EnumA'>
Traceback (most recent call last):
  File"Maps.py", line 15, in <module>
    print(EnumA.EnumB.member)
AttributeError: 'EnumA' object has no attribute 'member'


您不能使用enumstdlib模块执行此操作。如果你尝试它:

1
2
3
4
5
6
7
8
9
class A(Enum):
    class B(Enum):
        a = 1
        b = 2
    class C(Enum):
        c = 1
        d = 2

A.B.a

…你会得到一个例外,比如:

1
AttributeError: 'A' object has no attribute 'a'

这是因为A的枚举值与A的实例类似,而不像其值类型的实例。就像持有int值的普通枚举在值上没有int方法一样,B也没有enum方法。比较:

1
2
3
4
5
class D(Enum):
    a = 1
    b = 2

D.a.bit_length()

当然,您可以显式访问基础值(intB类):

1
2
D.a.value.bit_length()
A.B.value.a

…但我怀疑这就是你想要的。

那么,您是否可以使用与IntEnum相同的技巧,将enumint子类化,使其枚举值为int值,如文档的其他部分所述?

不,因为您要子类化什么类型?不是enum;那已经是你喜欢的类型了。不能使用type(任意类的类型)。没有什么有用的。

因此,您必须使用具有不同设计的不同枚举实现来实现这一点。幸运的是,Pypi和ActiveState上有大约69105个不同的选项可供选择。

例如,当我在寻找类似SWIFT枚举(比Python/Java/枚举)更接近ML的ADT时,有人推荐我看EDCOX1(15)。我忘了这样做,但现在我刚刚做了,而且:

1
2
3
4
5
6
7
class A(makeobj.Obj):
    class B(makeobj.Obj):
        a, b = makeobj.keys(2)
    class C(makeobj.Obj):
        c, d = makeobj.keys(2)

print(A.B, A.B.b, A.B.b.name, A.B.b.value)

这给了你:

1
<Object: B -> [a:0, b:1]> <Value: B.b = 1> b 1

如果它在创建str/repr值时查看它的__qualname__而不是它的__name__,可能会很好,但如果不是这样,它看起来像是做了你想要的一切。它还有一些其他很酷的特性(不是我想要的,而是有趣的…)。