在python中订购枚举值
我希望能够安排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)
枚举的示例如下:
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。但我想先选单,再选双。
-
您的Enum在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()