HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Yet another lightweight Enum for Python 2.7

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
lightweightenumyetforanotherpython

Problem

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 co

Solution

An interesting bit of code. :)

The downsides would be the things missing from enum341:

  • printing a variable gives no indication that it's an enum and not a string



  • enums that have the same value will compare equal



  • depending on the value of the member, is won't always work



  • etc.



Plus the surprise other developers will have when your enum doesn't work like the now-standard Python Enum2.

On the bright side, you shouldn't have any problems with pickling.

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

2 See this answer for the standard Enum usage.

Context

StackExchange Code Review Q#109724, answer score: 5

Revisions (0)

No revisions yet.