Enum of enums in Python?

后端 未结 5 1248
萌比男神i
萌比男神i 2021-02-14 01:54

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:20

    Note The below is interesting, and may be useful, but as @abarnert noted the resulting A Enum doesn't have Enum members -- i.e. list(A) returns an empty list.


    Without commenting on whether an Enum of Enums is a good idea (I haven't yet decided ;) , this can be done... and with only a small amount of magic.

    You can either use the Constant class from this answer:

    class Constant:
        def __init__(self, value):
            self.value = value
        def __get__(self, *args):
            return self.value
        def __repr__(self):
            return '%s(%r)' % (self.__class__.__name__, self.value)
    

    Or you can use the new aenum library and its built-in skip desriptor decorator (which is what I will show).

    At any rate, by wrapping the subEnum classes in a descriptor they are sheltered from becoming members themselves.

    Your example then looks like:

    from aenum import Enum, skip
    
    class enumA(Enum):
        @skip
        class enumB(Enum):
            elementA = 'a'
            elementB = 'b'
        @skip
        class enumC(Enum):
            elementC = 'c'
            elementD = 'd'
    

    and you can then access them as:

    print(enumA)
    print(enumA.enumB)
    print(enumA.enumC.elementD)
    

    which gives you:

    
    
    enumC.elementD
    

    The difference between using Constant and skip is esoteric: in enumA's __dict__ 'enumB' will return a Constant object (if Constant was used) or if skip was used; normal access will always return .

    In Python 3.5+ you can even (un)pickle the nested Enums:

    print(pickle.loads(pickle.dumps(enumA.enumC.elementD)) is enumA.enumC.elementD)
    # True
    

    Do note that the subEnum doesn't include the parent Enum in it's display; if that's important I would suggest enhancing EnumMeta to recognize the Constant descriptor and modify its contained class' __repr__ -- but I'll leave that as an exercise for the reader. ;)

提交回复
热议问题