I'm trying to create an Enum
subclass whose values use their definition order as their natural sort order, like in the example below:
@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)}
Is there a more direct way to get the position of an enum value in its definition order or otherwise a better way to do this?
If this is a pattern you need often, or if the values are important and cannot be replaced by numbers, make a custom Enum you can inherit from:
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
This allows you to keep any other value instead, while still sorting according to definition order.
class SelectionType(ByDefinitionOrderEnum):
character = 'character'
word = 'word'
sentence = 'sentence'
paragraph = 'paragraph'
and in use:
>>> SelectionType.word < SelectionType.sentence
True
>>> SelectionType.word.value < SelectionType.sentence.value
False
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With