我试图创建一个Enum
子类,其值使用其定义顺序作为其自然排序顺序,如下例所示:
@functools.total_ordering
class SelectionType(enum.Enum):
character = 'character'
word = 'word'
sentence = 'sentence'
paragraph = 'paragraph'
def __le__(self, other):
if not isinstance(other, SelectionType):
return NotImplemented
return self._positions[self] < self._positions[other]
SelectionType._positions = {x: i for i, x in enumerate(SelectionType)}
是否有更直接的方法来获取枚举值在其定义顺序中的位置,或者更好的方法来执行此操作?
答案 0 :(得分:4)
您可以将位置编码为值。使用.name
获取名称。
class SelectionType(enum.Enum):
character = 1
word = 2
sentence = 3
paragraph = 4
# copy the OrderedEnum recipe from https://docs.python.org/3/library/enum.html#orderedenum
def __lt__(self, other):
if self.__class__ is other.__class__:
return self.value < other.value
return NotImplemented
>>> SelectionType.word.name
'word'
>>> SelectionType.word < SelectionType.sentence
True
在Python 3.6+上,您可以使用enum.auto()
来避免对位置进行硬编码。
class SelectionType(enum.Enum):
character = enum.auto()
word = enum.auto()
sentence = enum.auto()
paragraph = enum.auto()
答案 1 :(得分:4)
如果这是您经常需要的模式,或者如果值很重要且无法用数字替换,请创建一个可以继承的自定义枚举:
import enum
class ByDefinitionOrderEnum(enum.Enum):
def __init__(self, *args):
try:
# attempt to initialize other parents in the hierarchy
super().__init__(*args)
except TypeError:
# ignore -- there are no other parents
pass
ordered = len(self.__class__.__members__) + 1
self._order = ordered
def __ge__(self, other):
if self.__class__ is other.__class__:
return self._order >= other._order
return NotImplemented
def __gt__(self, other):
if self.__class__ is other.__class__:
return self._order > other._order
return NotImplemented
def __le__(self, other):
if self.__class__ is other.__class__:
return self._order <= other._order
return NotImplemented
def __lt__(self, other):
if self.__class__ is other.__class__:
return self._order < other._order
return NotImplemented
这允许您保留任何其他值,同时仍按照定义顺序进行排序。
class SelectionType(ByDefinitionOrderEnum):
character = 'character'
word = 'word'
sentence = 'sentence'
paragraph = 'paragraph'
并在使用中:
>>> SelectionType.word < SelectionType.sentence
True
>>> SelectionType.word.value < SelectionType.sentence.value
False