Можно ли выполнить встроенную инициализацию с помощью класса Enum python - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь сделать некоторые перечисления в стиле C, изменяя AutoNumber из https://docs.python.org/3.4/library/enum.html#interesting -примера

Я не могу понять, как получить __init__ кодированная функция.

class MyEnum (Enum):
    def __new__(cls):
        value = len(cls.__members__) + 1
        obj = object.__new__(cls)
        obj._value_ = value
        return obj

    def __new__(cls, value):
        super().__new__(cls, value) # It doesn't matter what I put here...

class ThingsToDo (MyEnum):
        first_thing = 30
        second_thing = ()
        ...
        another_thing = 50
        yet_another_thing = ()

И так далее, возможность установки значения во время инициализации. Я пробовал множество различных способов определения __new__, но в основном получаю эту ошибку:

  File "/usr/lib/python3.7/enum.py", line 218, in __new__
      enum_member = __new__(enum_class, *args)
 TypeError: __new__() takes 1 positional argument but 2 were given

, хотя вызов в приведенном выше коде дает мне следующее:

  File "/usr/lib/python3.7/enum.py", line 218, in __new__
    enum_member = __new__(enum_class, *args)
  File "./codecs.py", line 34, in __new__
    super().__new__(cls, value)
  File "/usr/lib/python3.7/enum.py", line 564, in __new__
    raise exc
  File "/usr/lib/python3.7/enum.py", line 548, in __new__
    result = cls._missing_(value)
  File "/usr/lib/python3.7/enum.py", line 577, in _missing_
    raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 30 is not a valid ThingsToDo

Я либо упускаю что-то простое, либо это большая задача, чем я думал. Я не привязан к Enum , поэтому, если есть лучший способ сделать это, я готов к этому.

1 Ответ

1 голос
/ 22 апреля 2020

Надеюсь, ваш второй __new__ должен был быть __init__ - но это все равно будет неверно. То, что вы (возможно) хотите, чтобы ваш __new__ выглядел так:

    def __new__(cls, value=None):
        if value is None:
            value = len(cls.__members__) + 1
        obj = object.__new__(cls)
        obj._value_ = value
        return obj

Однако, с учетом вышеприведенного __new__, ваши члены ThingsToDo enum будут:

>>> list(ThingsToDo)
[
  <ThingsToDo.first_thing: 30>,
  <ThingsToDo.second_thing: 2>,
  <ThingsToDo.another_thing: 50>,
  <ThingsToDo.yet_another_thing: 4>,
  ]

Обратите внимание, что second и yet_another_thing имеют значения 2 и 4, а не 31 и 51. Если это то, что вы ожидали, тогда вы хороши для go!

В противном случае, если 31 и 51 - то, что вы ищете, тогда вам нужно будет найти __new__ значение из последнего определенного перечисления и его приращение:

    def __new__(cls, value=None):
        if value is None:
            if not cls.__members__:
                value = 1
            else:
                last_enum_name = cls._member_names_[-1]
                last_enum = cls.__members__[last_enum_name]
                value = last_enum.value + 1 
        obj = object.__new__(cls)
        obj._value_ = value
        return obj
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...