I have a simple Enum
:
class E(Enum):
A = 'a'
B = 'b'
To access 'a'
I must type E.A.value
. However, the value
is the only thing I need from the Enum object.
How to write an Enum, where 'a'
could be accessed just by E.A
?
I have a simple Enum
:
class E(Enum):
A = 'a'
B = 'b'
To access 'a'
I must type E.A.value
. However, the value
is the only thing I need from the Enum object.
How to write an Enum, where 'a'
could be accessed just by E.A
?
Using an int as value was just an example. It should actually be a user-defined class.
If you mixin a class/type with the Enum
, then simply accessing the member itself will give you a subtype of that type:
from enum import Enum
class MyClass:
def __init__(self, color):
self.color = color
class MyEnum(MyClass, Enum):
first = 'red'
second = 'green'
third = 'blue'
and in use:
>>> MyEnum.first
<MyEnum.first: 'red'>
>>> MyEnum.first.color
'red'
>>> type(MyEnum.first)
<enum 'MyEnum'>
>>> isinstance(MyEnum.first, MyClass)
True
Disclosure: I am the author of the Python stdlib Enum
, the enum34
backport, and the Advanced Enumeration (aenum
) library.
I looked around a lot, and I couldn't find a good solution to this problem using the Enum
class you're trying to use. However, if you're willing to eschew the idea of using the Enum
as a superclass, you can kludge this together:
class Demo:
# something with a 'value' method in it
def __init__(self, val):
self.value = val
def custom_enum(cls):
# class decorator to get __getattribute__() to work properly
# this is necessary because __getattribute__() only exists as an instance method,
# and there seems to be no direct equivalent for class methods
return cls()
@custom_enum
class E:
# first, define our enumerated variables in a dict
_enums = {
'A': Demo('a'),
'B': Demo('b'),
'chicken': Demo('cluck')
}
# then, override __getattribute__() to first get the key from the dict,
# and return the .value property of it
def __getattribute__(self, key):
# because of the decorator, we can't call self._enums or else we get a RecursionError
# therefore, we need to implicitly subclass `object`, and then
# deliberately invoke object.__getattribute__ on self, to access _enums
my_enums = object.__getattribute__(self, '_enums')
return my_enums[key].value
Actually defining the values of your enumerable is as simple as editing the _enums
dict. And once you've done so, it should work roughly as you want it to:
>>> E.A
'a'
>>> E.B
'b'
>>> E.chicken
'cluck'
From here you could modify the implementation however necessary (such as returning an AttributeError
instead of a KeyError
, for example, or overriding __setattr__()
to make enum values non-settable, or whatever).