在Python中排序枚举值

问题描述 投票:0回答:4

我希望能够安排 Enum 的顺序。有人建议如何解决这个问题吗?

以下 Enum 元类正在使用:

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)

Enum 的示例如下:

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() 

通过打印 Enum SideHemType,首先打印 Double,然后打印 Single。但我想要先单人,然后再双人。

python enums meta
4个回答
9
投票

如果您使用的是 Python3.4,您可以使用新的

enum.Enum
类型,它会记住枚举成员声明的顺序。

如果您使用的是较早版本的 Python,则应使用 PyPI

 提供的 
enum34 包,它支持 Python 回至 2.4。

如果在Python3中使用

enum34

包,它也会记住成员声明的顺序。如果在 Python 2 中使用,它支持额外的 
_order_
 属性:

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"
    

9
投票
使用

IntEnum 包中的

enum
 并使用整数值指定所需的顺序:

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

True


5
投票
这个怎么样

class MyEnum(enum.Enum): first_item = 'bla bla' whatever = 'blubb' another_one = 'blobb' def __lt__(self, other: 'MyEnum'): if self == other: return False # the following works because the order of elements in the definition is preserved for elem in MyEnum: if self == elem: return True elif other == elem: return False raise RuntimeError('Bug: we should never arrive here') # I just like being pedantic def __gt__(self, other): return not (self < other) def __ge__(self, other): if self == other: return True return not (self < other)
    

1
投票
您的枚举在 3 个位置失去了顺序。首先,类主体上的属性存储在字典中,然后将这些项目复制到另一个字典中。最后你的

values()

 返回第三个字典。字典不保存顺序,无法获取类体内属性的顺序。

对于这个系统,最简单的就是有一个变量

__ordering__ = [ 'single', 'double' ]
并使 

values()

 返回元组列表(如 
dict.items()
)。

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[attr_name.lower()] = value ordering = attrs.get('__ordering__') if ordering == None: ordering = sorted(cls_choices.keys()) def choices(cls): return dict(cls_choices) def values(cls, value=None): if value is None: return [ (k, cls_choices[k] ) for k in ordering ] elif not isinstance(value, basestring): return [ (k, cls_choices[k] ) for k in value ] else: return unicode(cls_choices.get(value)) def keys(cls, nil=False): items = list(ordering) 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) class SideHemType: __ordering__ = ['double', 'single'] __metaclass__ = EnumMeta Single = "Single side hem for opaque fabrics" Double = "Double side hem for transparent fabrics" print SideHemType.keys() print SideHemType.values()
    
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.