Basically, I want an enum that reuses keys, which is explicitly not allowed by enum.Enum
. The reason is that I want the user to be able to define the same behavior with multiple strings, or the enum itself, as function parameters, but then represent it with a unique, unambiguous enum internally.
I feel like my workaround is kind of ugly. How can I implement this feature better? Should I use something other than Enum? What should that be?
class Norm(Enum):
"enum to select the real quantity to represent some complex quantity"
REAL, IMAG, ABS, PHASE = 1, 2, 3, 4
@classmethod
def str_vals(cls):
return {
"re": cls.REAL,
"real": cls.REAL,
"im": cls.IMAG,
"imag": cls.IMAG,
"imaginary": cls.IMAG,
"abs": cls.ABS,
"ampl": cls.ABS,
"amplitude": cls.ABS,
"magnitude": cls.ABS,
"ang": cls.PHASE,
"angle": cls.PHASE,
"ph": cls.PHASE,
"phase": cls.PHASE,
}
@staticmethod
def to_norm(s: Union['Norm', str]):
if isinstance(s, str):
return Norm.str_valst()[s.lower()]
elif isinstance(s, Norm):
# For simplicity, the constructor should accept either a string
# or an already constructed norm. This is so the user can use both in
# most functions as an input.
return s
else:
raise ValueError("invalid identifier: " + s.__repr__)
This way:
# an enum can be defined as
n = Norm.ABS # or
n = Norm.to_norm("ampl")
# and my functions would be like
some_func(x, norm_type: Union[str, Norm]):
n = Norm.to_norm(norm_type)
But it would be so much nicer if I could do as with a normal enum:
n1 = Norm("abs")
n2 = Norm("ampl")
# where the following holds:
(n1 == n2) == True and n1 is n2
# and my functions would be like
some_func(x, norm_type: Union[str, Norm]):
n = Norm(norm_type)