我很高兴了解到
Enum
类型可以有效地携带命名属性:
from enum import Enum
class ActivityType(Enum):
NEXT = 0, "N"
JOIN = 3, "J"
DIVIDE_REAR = 1, "DR"
DIVIDE_FRONT = 2, "DF"
def __init__(self, xml_code, label):
self.xml_code = xml_code
self.label = label
assert ActivityType.JOIN.label == "J"
assert ActivityType.DIVIDE_FRONT.xml_code == 2
我怎样才能对
Flag
枚举做类似的事情?在这里,某些东西可以有 PowerType
的组合,并且字符串表示形式对于每个组合都有一个代码,这些代码以特定的顺序组合:
class PowerType(Flag):
NONE = 0
AC_OVERHEAD = auto()
DC_3RAIL = auto()
DIESEL = auto()
def xml_code(self):
powertype_subcode = {
PowerType.AC_OVERHEAD: "O",
PowerType.DC_3RAIL: "3",
PowerType.DIESEL: "D",
}
return "".join(sc for pt, sc in powertype_subcode.items() if pt & self)
assert (PowerType.DIESEL | PowerType.DC_3RAIL).xml_code() == "3D"
assert (PowerType.AC_OVERHEAD | PowerType.DC_3RAIL).xml_code() == "O3"
我想做这样的事情并消除那个
powertype_subcode
字典:
class PowerType(Flag):
NONE = 0, ""
AC_OVERHEAD = auto(), "O"
DC_3RAIL = auto(), "3"
DIESEL = auto(), "D"
def __init__(self, flag, xml_code):
self.flag = flag
self._xml_subcode = xml_code
def xml_code(self):
return "".join(pt._xml_subcode for pt in PowerType if pt & self)
然而,这会导致
auto()
和 _generate_next_value_
出现问题,如果我解决这个问题,它无法对元组值进行按位运算。
解决方案是将
.value
属性设置为仅标志值(0, 1, 2, 4...),这只能在 __new__
中完成。其他数据存储为属性:
class PowerType(Flag):
NONE = 0
AC_OVERHEAD = auto(), "O"
DC_3RAIL = auto(), "3"
DIESEL = auto(), "D"
def __new__(cls, flag, xml_code = ""):
obj = object.__new__(cls)
obj._value_ = flag
obj._xml_subcode = xml_code
return obj
def xml_code(self):
return "".join(pt._xml_subcode for pt in PowerType if pt & self)
# Assertions still pass
assert (PowerType.DIESEL | PowerType.DC_3RAIL).xml_code() == "3D"
assert (PowerType.AC_OVERHEAD | PowerType.DC_3RAIL).xml_code() == "O3"
标志上的属性可能存在的问题是它们存在于单个标志中,但不存在于组合标志中:
ac = PowerType.AC_OVERHEAD
acdc = PowerType.AC_OVERHEAD | PowerType.DC_3RAIL
ac._xml_subcode # "O"
acdc._xml_subcode # AttributeError: 'PowerType' object has no attribute '_xml_subcode'
不抬头也没有问题