Enum of enums in Python?

后端 未结 5 2060
不思量自难忘°
不思量自难忘° 2021-02-14 01:20

Is it possible to have an enum of enums in Python? For example, I\'d like to have

enumA
    enumB
        elementA
        elementB
    enumC
        elementC
          


        
5条回答
  •  余生分开走
    2021-02-14 02:16

    You can't do this with the enum stdlib module. If you try it:

    class A(Enum):
        class B(Enum):
            a = 1
            b = 2
        class C(Enum):
            c = 1
            d = 2
    
    A.B.a
    

    … you'll just get an exception like:

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

    This is because the enumeration values of A act like instances of A, not like instances of their value type. Just like a normal enum holding int values doesn't have int methods on the values, the B won't have Enum methods. Compare:

    class D(Enum):
        a = 1
        b = 2
    
    D.a.bit_length()
    

    You can, of course, access the underlying value (the int, or the B class) explicitly:

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

    … but I doubt that's what you want here.


    So, could you use the same trick that IntEnum uses, of subclassing both Enum and int so that its enumeration values are int values, as described in the Others section of the docs?

    No, because what type would you subclass? Not Enum; that's already your type. You can't use type (the type of arbitrary classes). There's nothing that works.

    So, you'd have to use a different Enum implementation with a different design to make this work. Fortunately, there are about 69105 different ones on PyPI and ActiveState to choose from.


    For example, when I was looking at building something similar to Swift enumerations (which are closer to ML ADTs than Python/Java/etc. enumerations), someone recommended I look at makeobj. I forgot to do so, but now I just did, and:

    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)
    

    This gives you:

     [a:0, b:1]>  b 1
    

    It might be nice if it looked at its __qualname__ instead of its __name__ for creating the str/repr values, but otherwise it looks like it does everything you want. And it has some other cool features (not exactly what I was looking for, but interesting…).

提交回复
热议问题