我试图将IntEnum子类化,以将成员的值开始为某个值,然后自动为后续成员设置该值。这是我的课程:
class Abc(IntEnum):
def __init__(self, n=100):
super().__init__()
self._value_ = n + len(self.__class__.__members__)
A = () # 100
B = () # 101
Abc.A == Abc.B # expects False, but gets True
如上所示,成员之间的比较不正确。当打印出Abc。 dict 时,我注意到_value2member_map_也不正确。
mappingproxy({'A': <Abc.A: 100>,
'B': <Abc.B: 101>,
'__doc__': 'An enumeration.',
'__init__': <function __main__.Abc.__init__>,
'__module__': '__main__',
'__new__': <function enum.Enum.__new__>,
'_generate_next_value_': <function enum.Enum._generate_next_value_>,
'_member_map_': OrderedDict([('A', <Abc.A: 100>),
('B', <Abc.B: 101>)]),
'_member_names_': ['A', 'B'],
'_member_type_': int,
'_value2member_map_': {0: <Abc.B: 101>}})
请注意'_value2member_map_'如何具有键0而不是预期值100和101。我必须在init函数中缺少某些内容,但是我无法弄清楚如何正确地实现我的预期。任何帮助表示赞赏。 谢谢。
答案 0 :(得分:3)
首先,还有一种更惯用且简单的方法来完成您似乎想做的事情:
class Abc(IntEnum):
A = 100
B = auto()
或者,考虑到您无论如何都将100和101作为注释,实时代码总是比注释更好:
class Abc(IntEnum):
A = 100
B = 101
您没有做 这两个事实,这向读者发出了一个信号,即您可能正在做一些更复杂的事情。据我所知,除了你不是,所以这是一种误导。
此外,您正在组合两种具有截然相反含义的模式:the docs说,使用()
惯用法“向用户表示这些值并不重要”,而使用{{ 1}}显然意味着这些枚举常量的数值不仅很重要,而且还很重要。
不仅如此,用户还必须通读方法代码以找出那些重要的数值,而不是立即读取它们。
无论如何,如果您想使其正常工作,问题在于初始化后替换IntEnum
并没有任何好处,实际上却没有。
您要覆盖的是_value_
,而不是the auto-numbering example in the docs中的__new__
。
但是这里有两个区别(两者都与您使用__init__
而不是IntEnum
的事实有关)
Enum
,因为object.__new__
是IntEnum
,并且int
不能用于诸如object.__new__
之类的内置类型的实例。您可以通过浏览int
的mro来动态地找出正确的基类,或者您也可以在此处硬编码cls
。int
,则可能仍需要一个。)所以:
IntEnum