Python枚举组合

时间:2017-09-06 10:57:00

标签: python enums metaprogramming python-3.5 metaclass

我想基于两个现有的类创建一个新的Enum(IntEnum)类。有一个可行的解决方案,如下所示:

from enum import unique, IntEnum
from itertools import chain
from collections import OrderedDict

@unique
class FirstEnumClass(IntEnum):
    a = 1
    b = 2

@unique
class SecondEnumClass(IntEnum):
    c = 3
    d = 4

# here a combined class is created:
CombinedEnumClass = unique(IntEnum('CombinedEnumClass', OrderedDict([(i.name, i.value) for i in chain(FirstEnumClass, SecondEnumClass)])))

我的问题:是否有一种奇特的方法来实现这一目标,以便有适当的类定义?喜欢重写一些元类方法,或者等等?我想要这样的东西,所以也可以给出docstring:

@unique
class CombinedEnumClass(IntEnum):
    """ docstring """
    # magic needed here

有什么想法吗?谢谢!

2 个答案:

答案 0 :(得分:4)

Python 2

使用vars()的技巧可以实现:

class CombinedEnum(IntEnum):
    """ doc string """
    cls = vars()
    for member in chain(list(FirstEnumClass), list(SecondEnumClass)):
        cls[member.name] = member.value
    del member, cls

print(list(CombinedEnum))

这是因为:

  • vars()返回当前名称空间
  • 修改该命名空间修改类

我们删除membercls,因为我们不希望他们成为会员。

Python 3

以上内容(尚未)在Python3 3.4和3.5中使用新的Enum(不确定3.6)。一轮工作是使用aenum代替,这样我们就可以告诉Enum忽略某些名称:

from aenum import IntEnum

class CombinedEnum(IntEnum):
    """ doc string """
    _ignore_ = 'member cls'
    cls = vars()
    for member in chain(list(FirstEnumClass), list(SecondEnumClass)):
        cls[member.name] = member.value

1 披露:我是Python stdlib Enumenum34 backportAdvanced Enumeration (aenum)图书馆的作者。

答案 1 :(得分:0)

prevents explicitly来做到这一点:

  

仅当枚举不允许时才允许对枚举进行子类化   定义任何成员。

     

允许定义成员的枚举的子类化将导致a   违反了一些类型和实例的重要不变量。在   另一方面,允许共享一些常见行为是有意义的   在一组枚举之间。

因此,我发现Stackoverflow answer使用了几乎与您相同的解决方法。我认为这是唯一的方法。