Hacker News new | ask | show | jobs
by morphyn 4791 days ago
Doesn't the 'functional API' make up for it ? `Animal = Enum('Animal', ['ant', 'bee', 'cat', 'dog'])`
1 comments

The functional API could stand to be improved a bit:

    >>> Animal = Enum(['ant, 'bee', 'cat', 'dog'])
    >>> Animal.ANT
    'ant'
I'm not convinced it's useful to pass the class name into the functional API, but I would see value in having an easy API to create enumerated strings. It's easier to see what's going on in other environments (e.g. in a datastore, or in JavaScript) if you pass around string identifiers instead of ints.

Here's the class I've been using to do that:

    class Constants(object):
        def __init__(self, names, enum = False):
            self._names = frozenset(names)
        
            if enum:
                for (i, name) in enumerate(self._names):
                    setattr(self, name.upper(), i)
                
            else:
                for name in self._names:
                    setattr(self, name.upper(), name.lower())
            
            self.frozen = True
    
    
        def keys(self):
            return [name.upper() for name in self._names]
    
    
        def values(self):
            return [getattr(self, name.upper()) for name in self._names]
    
    
        def __setattr__(self, key, value):
            if getattr(self, 'frozen', False):
                raise Exception("Constants cannot be modified after instantiation")
            else:
                object.__setattr__(self, key, value)
Example:

    >>> ImportMethod = Constants(
    >>>     [
    >>>         'email', 
    >>>         'manual_upload', 
    >>>         'api',
    >>>     ]
    >>> )
    >>> 
    >>> print(ImportMethod.API)
    'api'
There is a technical reason why the class name is passed into the API, and it's the same for other functions which create types (collections.namedtuple(), and type(), for example). You want to be able to print out the class name when you print an enum, but there is no other reliable way to figure out the class name. In Python, a class is just another value, like functions and integers and its name is nothing special. When you define a class normally, the name and dictionary get passed to the type() function.
I understand that, but I'm not sure it matter. Is it worth the ugliness in the API to print out the class name when you run print? Is 'api' that much worse than "ImportMethod.API"?
That's not all it's there for. Python programmers expect to be able to do things like print(obj.__class__.__name__). You're definitely free to write your own alternative Enum, however, since it's just a library function.