Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ordering enum value in python

Tags:

python

enums

meta

I would like to be able to arrange the ordering of Enum. Has somebody suggestions how this can be solved?

The following Enum meta class is using:

class EnumMeta(type):
    def __new__(typ, name, bases, attrs):
        cls_attrs = {}
        cls_choices = []
        for attr_name, value in attrs.items():
            cls_attrs[attr_name] = attr_name.lower()
            if not attr_name.startswith("__"):
                cls_choices.append((attr_name.lower(), value))

        def choices(cls):
            return cls_choices

        def values(cls, value=None):
            if value is None:
                return {choice[0]: unicode(choice[1]) for choice in cls.choices()}
            elif isinstance(value, list):
                return {choice[0]: unicode(choice[1]) for choice in cls.choices() if choice[0] in value}
            else:
                return unicode(dict(cls.choices()).get(value))

        def keys(cls, nil=False):
            items = [item[0] for item in cls.choices()]
            if nil:
                items.append('')

            return items

        def combined_length(cls):
            return len(",".join(cls.values().keys()))

        def max_length(cls):
            return max(map(len, cls.values().keys()))

        cls_attrs['choices'] = classmethod(choices)
        cls_attrs['values'] = classmethod(values)
        cls_attrs['keys'] = classmethod(keys)
        cls_attrs['combined_length'] = classmethod(combined_length)
        cls_attrs['max_length'] = classmethod(max_length)

        return type(name, bases, cls_attrs)

An example of an Enum is as follow:

class SideHemType:
    __ordering__ = ['double', 'single']
    __metaclass__ = EnumMeta

    Single = "Single side hem for opaque fabrics"
    Double = "Double side hem for transparent fabrics"


  class TestEnumOrdering:
        print SideHemType.keys()
        print SideHemType.values() 

By printing the Enum SideHemType first Double is printed and then Single. But I would like first Single and then Double.

like image 768
Robert Avatar asked Aug 23 '13 09:08

Robert


2 Answers

If you are using Python3.4 you can use the new enum.Enum type, which remembers the order the enum members are declared in.

If you are using an earlier Python, you should use the enum34 package available from PyPI, which supports Pythons back to 2.4.

The enum34 package, if used in Python3, also remembers the order of member declarations. If used in Python 2 it supports an extra _order_ attribute:

from enum import Enum

class SideHemType(Enum):

    _order_ = 'Single Double'  # only needed in Python 2

    Single = "Single side hem for opaque fabrics"
    Double = "Double side hem for transparent fabrics"

    @classmethod
    def combined_length(cls):
        return len(",".join(mbr.name for mbr in cls))

    @classmethod
    def max_length(cls):
        return max(map(len, (mbr.name for mbr in cls)))


print list(SideHemType)  # [SideHemType.Single, SideHemType.Double]

print SideHemType.Double.value  # "Double side hem for transparent fabrics"
like image 74
Ethan Furman Avatar answered Oct 01 '22 14:10

Ethan Furman


Use IntEnum from the enum package and use the integer values to specify the order that you want:

class Shape(IntEnum):
    CIRCLE = 1
    SQUARE = 2
Shape.CIRCLE < Shape.SQUARE

Prints True.

like image 44
Nate Glenn Avatar answered Oct 01 '22 13:10

Nate Glenn