【问题标题】:Is there an easier way of sorting Enum members in Python 2?有没有更简单的方法在 Python 2 中对 Enum 成员进行排序?
【发布时间】:2018-04-26 17:45:29
【问题描述】:

我在一个项目中坚持使用 Python 2.7,并且我有几个 Enums 用于将 Python 框架 (OpenERP) 与旧框架集成。在 Python 2 中,默认为 Enums are not ordered

>>> from enum import Enum
>>> class Color(Enum):
...   RED = 1
...   GREEN = 2
...   BLUE = 3
... 
>>> list(Color)
[<Color.BLUE: 3>, <Color.RED: 1>, <Color.GREEN: 2>]

如果顺序很重要,则必须手动添加_order_ = 'member1, member2, member3' 属性。

>>> class Color(Enum):
...   _order_ = 'RED GREEN BLUE'
...   RED = 1
...   GREEN = 2
...   BLUE = 3
... 
>>> list(Color)
[<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>]

这适用于较小的 Enums,但我有几个名称在 10 到 50 个之间,而且在添加/删除名称时,输入、读取或保持顺序实在是太多了。

还有其他选择吗?

【问题讨论】:

  • 可以用 enum34 包吗?它已被向后移植到 Python 2.7。
  • @Sebastian:上面的例子是使用enum34 包。这并不明显,因为enum34 安装为enum

标签: python python-2.7 enums


【解决方案1】:

截至aenum 2.1.21_order_ 属性可以是一个函数;此函数将用作keysort() 以将Enum 成员按正确顺序排列:

from aenum import Enum

class Pres(str, Enum):

    _init_ = 'value, precedence'        # footnote 2
    _order_ = lambda m: m.precedence    # footnote 3

    PRESIDENT = 'president', 1
    COUNSELOR_1 = 'first counselor', 2
    COUNSELOR_2 = 'second counselor', 3
    SECRETARY = 'secretary', 4

    def __repr__(self):
        "added so example below is clearer"
        return '<%s.%s>' % (self.__class__.__name__, self.name)

并在使用中:

>>> list(Pres)
[<Pres.PRESIDENT>, <Pres.COUNSELOR_1>, <Pres.COUNSELOR_2>, <Pres.SECRETARY>]

虽然我不会更容易地调用这个下一个版本,但如果你不能使用aenum,并且不想尝试维护一个巨大的_order_,那么可以使用Functional API

Pres = Enum('Pres', (
        ('PRESIDENT', 'president'),          # comment here
        ('COUNSELOR_1', 'first counselor'),  # more comments here
        ('COUNSELOR_2', 'second counselor'), # you get the idea ;)
        ('SECRETARY', 'secretary'),
        ),
        type=str,
        )

def pres_repr(self):
    "added so example below is clearer"
    return '<%s.%s>' % (self.__class__.__name__, self.name)

Pres.__repr__ = pres_repr

丑陋,但它有效。但是,如果需要 precedence 字段,它将不起作用。


1 披露:我是Python stdlib Enumenum34 backportAdvanced Enumeration (aenum) 库的作者。

2_init_ 在这种情况下是必需的,因为我不希望将 precedence 值传递给 str 构造函数。

3 键函数将被赋予一个参数:

  • 没有_init_ -> (name, value) 的元组,其中值也可能是一个元组(在上面的示例中应该是)
  • 带有_init_ -> 带有name 字段的aenum.NamedTuple 以及_init_ 中的任何字段(因此在上面的示例中为namevalueprecedence

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-21
    • 2010-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 1970-01-01
    相关资源
    最近更新 更多