In python you can define a typed enum with auto values:
import enum
from enum import auto
class Ordinals(enum.IntEnum):
FIRST = auto()
SECOND = auto()
THIRD = auto()
Ordinals.FIRST == 1 #=> True
And you can also define a typed enum with arguments: (Example from docs):
class Coordinate(bytes, Enum):
"""
Coordinate with binary codes that can be indexed by the int code.
"""
def __new__(cls, value, label, unit):
obj = bytes.__new__(cls, [value])
obj._value_ = value
obj.label = label
obj.unit = unit
return obj
PX = (0, 'P.X', 'km')
PY = (1, 'P.Y', 'km')
VX = (2, 'V.X', 'km/s')
VY = (3, 'V.Y', 'km/s')
Coordinate.PX._name_ #=> 'PX'
Coordinate.PX == bytes([0]) #=> True
Coordinate.PX.label #=> 'P.X'
Furthermore, you can define an enum that looks up a value by the name:
class LetterOrdinals(enum.IntEnum):
def _generate_next_value_(name, *_):
return ord(name)
A = auto()
B = auto()
LetterOrdinals.A == 65 #=> True
Now say I want to combine all three and have a typed enum that generates a value from the name and allows for arguments to __new__/__init__. Is this possible? The first problem I run into is that auto no longer works on the value. it seems like if auto isn't the entire value, then it skips generating the value. Conversely, if it doesn't generate the value, the name is not available to __new__ or __init__. Here's an example that doesn't work (and I've tried variants on this):
class Coordinate(bytes, Enum):
def _generate_next_value_(name, *_):
return [ord(letter) for letter in value]
def __new__(cls, value, label, unit):
obj = bytes.__new__(cls, [*value])
obj._value_ = value
obj.label = label
obj.unit = unit
return obj
PX = (auto(), 'P.X', 'km')
PY = (auto(), 'P.Y', 'km')
VX = (auto(), 'V.X', 'km/s')
VY = ([2,2], 'V.Y', 'km/s')
# never generates the auto value, causes errors
So is there a good way around this?