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).