Как я могу переопределить конструктор enum? - PullRequest
1 голос
/ 11 февраля 2020

Я хочу создать перечисление, которое хранит двоичное значение, но которому я могу передать любое значение (оно будет хранить value % 2).

То есть: я хочу использовать «официальное» Enum введите с Python3, но измените конструктор.

Я попробовал этот код:

from enum import Enum

class Color(Enum):
    black = 0
    red = 1

    def __new__(cls, value):
        super().__new__(cls, value % 2)

    def __str__(self):
        return self.name

Но я получаю ошибку:

>>> from ZCasino import *
ValueError: 0 is not a valid Couleur

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/felix/Téléchargements/ZCasino.py", line 12, in <module>
    class Couleur(Enum):
  File "/usr/lib/python3.8/enum.py", line 212, in __new__
    enum_member = __new__(enum_class, *args)
  File "/home/felix/Téléchargements/ZCasino.py", line 18, in __new__
    super().__new__(cls, value)
  File "/usr/lib/python3.8/enum.py", line 595, in __new__
    raise exc
  File "/usr/lib/python3.8/enum.py", line 579, in __new__
    result = cls._missing_(value)
  File "/usr/lib/python3.8/enum.py", line 608, in _missing_
    raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 0 is not a valid Couleur

Ответы [ 3 ]

1 голос
/ 11 февраля 2020

Новый метод класса, вероятно, будет лучшей идеей, чем переопределение __new__:

class Color(Enum):
    black = 0
    red = 1

    @classmethod
    def from_int(cls, x):
        return cls(x%2)

Тогда

>>> Color.from_int(6)
<Color.black: 0>
>>> Color.from_int(7)
<Color.red: 1>
1 голос
/ 11 февраля 2020

Вы можете воспользоваться новым методом _missing_:

from aenum import Enum

class Color(Enum):
    black = 0
    red = 1
    #
    def __str__(self):
        return self.name
    #
    @classmethod
    def _missing_(cls, value):
        return cls(value % 2)

и используется:

>>> list(Color)
[<Color.black: 0>, <Color.red: 1>]

>>> Color(3)
<Color.red: 1>

>>> Color(8)
<Color.black: 0>

_missing_ был представлен в Python 3.6. Если вам нужна поддержка более ранних Pythons, вы можете использовать библиотеку aenum 1 .

NB При вызове Color(7) вы не являетесь создание нового Color, но получение существующего <Color.black: 0>, созданного при создании самого Enum.


1 Раскрытие информации: я являюсь автором Python stdlib Enum, enum34 backport и расширенное перечисление (aenum) .

1 голос
/ 11 февраля 2020

Вам необходимо переопределить метод __new__ после определения метода:

( Возможно ли переопределить __new__ в перечислении для анализа строк в экземпляре? )

from enum import Enum

class Color(Enum):
    black = 0
    red = 1

    def __str__(self):
        return self.name

Couleur.__new__ = lambda cls, value: super(Couleur, cls).__new__(cls, value % 2)

...