1

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)
Neinstein
  • 958
  • 2
  • 11
  • 31

0 Answers0