Get Enum name from multiple values python
Asked Answered
E

1

28

I'm trying to get the name of a enum given one of its multiple values:

class DType(Enum):
    float32 = ["f", 8]
    double64 = ["d", 9]

when I try to get one value giving the name it works:

print DType["float32"].value[1]  # prints 8
print DType["float32"].value[0]  # prints f

but when I try to get the name out of a given value only errors will come:

print DataType(8).name
print DataType("f").name

raise ValueError("%s is not a valid %s" % (value, cls.name))

ValueError: 8 is not a valid DataType

ValueError: f is not a valid DataType

Is there a way to make this? Or am I using the wrong data structure?

Equipollent answered 4/4, 2017 at 9:7 Comment(1)
Enums can't have multiple value per name. Why do you need this, is one of these an alias? When would use use 'f' and when 9?Sisterinlaw
H
49

The easiest way is to use the aenum library1, which would look like this:

from aenum import MultiValueEnum

class DType(MultiValueEnum):
    float32 = "f", 8
    double64 = "d", 9

and in use:

>>> DType("f")
<DType.float32: 'f'>

>>> DType(9)
<DType.double64: 'd'>

As you can see, the first value listed is the canonical value, and shows up in the repr().

If you want all the possible values to show up, or need to use the stdlib Enum (Python 3.4+), then the answer found here is the basis of what you want (and will also work with aenum):

class DType(Enum):
    float32 = "f", 8
    double64 = "d", 9

    def __new__(cls, *values):
        obj = object.__new__(cls)
        # first value is canonical value
        obj._value_ = values[0]
        for other_value in values[1:]:
            cls._value2member_map_[other_value] = obj
        obj._all_values = values
        return obj

    def __repr__(self):
        return '<%s.%s: %s>' % (
                self.__class__.__name__,
                self._name_,
                ', '.join([repr(v) for v in self._all_values]),
                )

and in use:

>>> DType("f")
<DType.float32: 'f', 8>

>>> Dtype(9)
<DType.float32: 'd', 9>

1 Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

Hexagonal answered 4/4, 2017 at 14:28 Comment(6)
@Ruvalcaba: Glad to help. When an answer works for you, you should accept it (click on the green check mark by that answer's score).Hexagonal
Just change the import to: from aenum import MultiValueEnum class DType(MultiValueEnum): float32 = "f", 8 double64 = "d", 9Petrozavodsk
@EthanFurman Do you think MultiValueEnum might land into the standard library eventually?Stinkweed
@Rotareti: Hard to say. Having real-world use-cases would help prove the need, but even then Enum is meant as a building-block more than a whole bunch of comprehensive solutions.Hexagonal
How to get "8" or "9"?Mcdougall
@Nairum, you could create a @ property into Enum class and access with self._all_values[index of value you want to access], for example self._all_values[1].Chenab

© 2022 - 2024 — McMap. All rights reserved.