pythonpython-3.xenumsconstructoroverriding

How can I override the enum constructor?


I want to create an enum that stores a binary value, but to which I can pass any value (it will store value % 2).

That is : I want to use the "official" Enum type from Python3 but change the constructor.

I tried this code : 

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

But I get an error :

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

Solution

  • A new class method would probably be a better idea than overriding __new__:

    class Color(Enum):
        black = 0
        red = 1
    
        @classmethod
        def from_int(cls, x):
            return cls(x%2)
    

    Then

    >>> Color.from_int(6)
    <Color.black: 0>
    >>> Color.from_int(7)
    <Color.red: 1>