我希望能够安排 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。但我想要先单人,然后再双人。
如果您使用的是 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"
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)
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()