Use the order of definition of Enum as a natural order

I am trying to create a subclass Enumwhose values โ€‹โ€‹use their definition order as their natural sort order, as 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 enumeration value in its definition order, or else is there a better way to do this?

+4
source share
2 answers

You can encode positions as values. Use .nameto get the 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

In Python 3.6+, you can use enum.auto()to avoid hard coding of positions.

class SelectionType(enum.Enum):
    character = enum.auto()
    word = enum.auto()
    sentence = enum.auto()
    paragraph = enum.auto()
+3
source

, , Enum, :

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
+1

Source: https://habr.com/ru/post/1670429/


All Articles