How to extend Python Enum?

后端 未结 7 1065
广开言路
广开言路 2020-12-08 18:26

What is best practice for extending Enum type in Python 3.4 and is there even a possibility for do this?

For example:

from enum import E         


        
7条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-08 18:45

    I tested that way on 3.8. We may inherit existing enum but we need to do it also from base class (at last position).

    Docs:

    A new Enum class must have one base Enum class, up to one concrete data type, and as many object-based mixin classes as needed. The order of these base classes is:

    class EnumName([mix-in, ...,] [data-type,] base-enum):
        pass
    

    Example:

    class Cats(Enum):
        SIBERIAN = "siberian"
        SPHINX = "sphinx"
    
    
    class Animals(Cats, Enum):
        LABRADOR = "labrador"
        CORGI = "corgi"
    

    After that you may access Cats from Animals:

    >>> Animals.SIBERIAN
    
    

    But if you want to iterate over this enum, only new members were accessible:

    >>> list(Animals)
    [, ]
    

    Actually this way is for inheriting methods from base class, but you may use it for members with these restrictions.

    Another way (a bit hacky)

    As described above, to write some function to join two enums in one. I've wrote that example:

    def extend_enum(inherited_enum):
        def wrapper(added_enum):
            joined = {}
            for item in inherited_enum:
                joined[item.name] = item.value
            for item in added_enum:
                joined[item.name] = item.value
            return Enum(added_enum.__name__, joined)
        return wrapper
    
    
    class Cats(Enum):
        SIBERIAN = "siberian"
        SPHINX = "sphinx"
    
    
    @extend_enum(Cats)
    class Animals(Enum):
        LABRADOR = "labrador"
        CORGI = "corgi"
    

    But here we meet another problems. If we want to compare members it fails:

    >>> Animals.SIBERIAN == Cats.SIBERIAN
    False
    

    Here we may compare only names and values of newly created members:

    >>> Animals.SIBERIAN.value == Cats.SIBERIAN.value
    True
    

    But if we need iteration over new Enum, it works ok:

    >>> list(Animals)
    [, , , ]
    

    So choose your way: simple inheritance, inheritance emulation with decorator (recreation in fact), or adding a new dependency like aenum (I haven't tested it, but I expect it support all features I described).

提交回复
热议问题