简体   繁体   中英

Python 2: What is the most elegant/pythonic way of doing a enum with string interpretations?

I want a enum with predefined single character constants (good for storing in database) and string interpretation. Here is what I am thinking of:

class Fruits(Enum):
    APPLE = 'A'
    PEAR = 'P'
    BANANA = 'B'
    def __unicode__(self):
        if self == APPLE: return "Crunchy Apple"
        if self == PEAR: return "Sweet Pear"
        if self == BANANA: return "Long Banana"

But

fruit = Fruits.APPLE
print fruit.__unicode__()

gives

AttributeError: 'unicode' object has no attribute '__unicode__'

And besides there must be a more elegant way of doing it

How to do it better?

A couple observations:

  • You shouldn't call __dunder__ methods directly; instead use the matching command: unicode instead of __unicode__

  • I am unable to duplicate your problem

Using the stdlib Enum (3.4+) or the enum34 backport (Python 2.x) you will have to do it the hard way -- make your own base Enum class:

class EnumWithDescription(Enum):
    def __new__(cls, value, desc):
        member = object.__new__(cls)
        member._value_ = value
        member.description = desc
        return member
    def __unicode__(self):
        return self.description

class Fruits(EnumWithDescription):
    _order_ = 'APPLE PEAR BANANA'   # if using Python 2.x and order matters
    APPLE = 'A', 'Crunchy Apple'
    PEAR = 'P', 'Sweet Pear'
    BANANA = 'B', 'Long Banana'

and in use:

>>> fruit = Fruits.APPLE
>>> unicode(fruit)
u'Crunchy Apple'

If you can use the aenum library 1 you will have an easier time of it:

from aenum import Enum

class Fruits(Enum, init='value description'):
    APPLE = 'A', 'Crunchy Apple'
    PEAR = 'P', 'Sweet Pear'
    BANANA = 'B', 'Long Banana'
    def describe(self):
        return self.description

and in use:

fruit = Fruits.APPLE
fruit.describe()

Note that since unicode is the default in Python 3 I changed the name to describe .


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

The enum34 module has what you want.

from enum import Enum

class Fruits(Enum):
    apple = 'A'
    pear = 'P'
    banana = 'B'

fruit = Fruits.apple

print fruit.value
>> 'A'

Possibly even better is using integers

from enum import Enum

class Fruits(Enum):
    apple = 1
    pear = 2
    banana = 3

fruit = Fruits.apple

print fruit.value
>> 1

And recreate the object if you get it's value (from a database for instance) using:

fruit = Fruits(1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM