Home > Net >  Is it possible to assign different enums to same value in Python class?
Is it possible to assign different enums to same value in Python class?

Time:12-18

I want to write class for Enums in Python.

My issue is that I want to have same value for different enum inputs. For example:

class Animal(Enum):
    Cat = ['Perian cat', 'Bengal cat', 'Siamese cat']

So then I could use it like this:

some_animal = Animal('Persian cat')
print(some_animal)
>> Animal.Cat

I think it is not possible, but just to be sure I wanted to ask for that here.

UPDATE

I tried this solution:

class _Cat(Enum):
 BENGAL = 'Bengal cat'
 PERSIAN = 'Persian cat'
 SIAMESE = 'Siamese cat'

class Animal(Enum):
 Cat = _Cat

It works in that sense that I can access the values of the Cat class, but what I would like to achieve is something like this:

some_animal = Animal('Persian cat')
print(some_animal)
>> Animal.Cat.PERSIAN

Thanks.

CodePudding user response:

You can obtain a close result with the functional API. In fact the hard part in not to have multiple members with same value, but to have names which contain spaces (ie: cannot be identifiers):

Animal = Enum('Animal', (('Persian cat', 'cat'), ('Bengal cat', 'cat'),
                         ('Siamese cat', 'cat')))

Then you can do:

>>> print(Animal['Persian cat'].value)
cat

And you can control the equality of the members:

>>>Animal['Persian cat'] == Animal['Bengal cat']
True

But then your enum class becomes very close to a plain dict. If additionaly you intend to be able to add new members, then IMHO, it is a hint that what you want is not an Enum but a simple dict.

CodePudding user response:

The easiest method would be to use the MultiEnum from aenum:

from aenum import MultiValueEnum

class Animal(MultiValueEnum):
    CAT = 'Cat', 'Persian cat', 'Bengal cat', 'Siamese cat'
    DOG = 'Dog', 'Greyhound', 'Boxer', 'Great Dane'
    def __repr__(self):
        # make the repr not reduntant
        return "<%s.%s>" % (self.__class__.__name__, self.name)

and in use:

>>> Animal('Bengal cat')
<Animal.CAT>

>>>> Animal('Boxer')
<Animal.DOG>

If you need to stick with the stdlib version of Enum:

from enum import Enum

class Animal(Enum):
    #
    def __new__(cls, *values):
        member = object.__new__(cls)
        member._value_ = values[0]
        member.all_values = values
        return member
    #
    @classmethod
    def _missing_(cls, value):
        for member in cls:
            if value in member.all_values:
                return member
    #
    CAT = 'Cat', 'Persian cat', 'Bengal cat', 'Siamese cat'
    DOG = 'Dog', 'Greyhound', 'Boxer', 'Great Dane'
    def __repr__(self):
        # make the repr not reduntant
        return "<%s.%s>" % (self.__class__.__name__, self.name)

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

  • Related