I'm trying to develop a lightweight enum for Python 2.7. This question is downstream of the SO question here; for context, a streamlined version of the bulleted addendum to that question is replicated below:
My desired feature set is:
- Only having to type the enum name (or value) once in the source definition.
- Valid enum values exposed for IDE autocomplete.
- Enum values stored internally as comprehensible strings.
- Straightforward membership testing using native Python
in
.- Ability to import individual enum subclasses via, say,
from .enums import myEnum
, to avoid cluttering the local namespace with other enums I don't care about.- I would rather avoid introducing an additional package dependency by using
enum34
, as I don't (think I) need the feature set.
After reviewing the SO post here on recommendations for non-enum34
implementations of enums in Python 2.7, I also would add:
- Clean, readable definition of enum values.
To note, every form of dynamic namespace construction I've tried, in efforts to accomplish #1, has broken #2. I'm pretty sure at this point they're mutually exclusive.
In any event, my current solution goes as follows, defining an enum superclass with a metaclassed type with an iterator that returns all members with string content identical to the respective member names:
class SuperEnum(object):
class __metaclass__(type):
def __iter__(self):
for item in self.__dict__:
if item == self.__dict__[item]:
yield item
Each enum is then subclassed from this SuperEnum
, e.g.:
class myEnum(SuperEnum):
this = 'this'
that = 'that'
other = 'other'
The usage is working just as I want (except of course for #1), including for the IDE autocomplete of #2:
>>> myEnum.other
'other'
>>> 'this' in myEnum
True
>>> 'thing' in myEnum
False
>>> e = myEnum.other
>>> e in myEnum
True
This construction is far more concise than anything I'd set up around the time I posted the above-linked SO question, so the need to type the value name twice in the enum class definition isn't terribly bothersome. I'm still interested to know if there's any way to make #1 and #2 play nice together, though.
More generally: what might the weaknesses of this construction be? For my application, performance is of minor concern. There's always the possibility of value collisions, as described here, but using strings as the values dramatically reduces the likelihood. Security issues? Compatibility problems of some kind?