Python枚举组合
Python Enum combination
我想在两个现有的基础上创建一个新的枚举 (IntEnum) class。有一个可行的解决方案,如下所示:
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)])))
我的问题:是否有一种奇特的方法来实现这一点,以便有一个正确的 class 定义?比如重写一些 metaclass 方法,还是这样?我想要这样的东西,这样也可以给出文档字符串:
@unique
class CombinedEnumClass(IntEnum):
""" docstring """
# magic needed here
有什么想法吗?谢谢!
图书馆 prevents explicitly 这样做:
Subclassing an enumeration is allowed only if the enumeration does not
define any members.
Allowing subclassing of enums that define members would lead to a
violation of some important invariants of types and instances. On the
other hand, it makes sense to allow sharing some common behavior
between a group of enumerations.
因此,我发现 使用与您几乎相同的解决方法。我认为这是唯一的方法。
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()
returns 当前命名空间
- 修改该命名空间会修改 class
我们删除了 member
和 cls
,因为我们不希望他们成为会员。
Python 3
以上内容(还)不适用于 Python3 3.4 和 3.5(不确定 3.6)中的新 Enum
。变通办法是改用 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 Enum
, the enum34
backport, and the Advanced Enumeration (aenum
) 库的作者。
我想在两个现有的基础上创建一个新的枚举 (IntEnum) class。有一个可行的解决方案,如下所示:
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)])))
我的问题:是否有一种奇特的方法来实现这一点,以便有一个正确的 class 定义?比如重写一些 metaclass 方法,还是这样?我想要这样的东西,这样也可以给出文档字符串:
@unique
class CombinedEnumClass(IntEnum):
""" docstring """
# magic needed here
有什么想法吗?谢谢!
图书馆 prevents explicitly 这样做:
Subclassing an enumeration is allowed only if the enumeration does not define any members.
Allowing subclassing of enums that define members would lead to a violation of some important invariants of types and instances. On the other hand, it makes sense to allow sharing some common behavior between a group of enumerations.
因此,我发现
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()
returns 当前命名空间- 修改该命名空间会修改 class
我们删除了 member
和 cls
,因为我们不希望他们成为会员。
Python 3
以上内容(还)不适用于 Python3 3.4 和 3.5(不确定 3.6)中的新 Enum
。变通办法是改用 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 Enum
, the enum34
backport, and the Advanced Enumeration (aenum
) 库的作者。