如何在Python中比较字符串枚举

yvgpqqbh  于 2023-05-16  发布在  Python
关注(0)|答案(4)|浏览(123)

假设我有MyEnum枚举,我想为它定义总排序。我的方法是:

from enum import Enum
from functools import total_ordering

@total_ordering
class MyEnum(Enum):
    ONE = "one",
    TWO = "two",
    THREE = "three",

    def __eq__(self, other):
        if not isinstance(other, MyEnum):
            return False
        return self.value == other.value

    def __hash__(self):
        return self.value.__hash__()

    def __le__(self, other):
        if not isinstance(other, MyEnum):
            return False

        enum2int = {
            MyEnum.ONE: 1,
            MyEnum.TWO: 2,
            MyEnum.THREE: 3,
        }
        
        return enum2int[self] < enum2int[other]

但这容易出错,而且很麻烦,因为我需要列出枚举值两次。有更好的方法吗?
我明白如果我使用int值甚至IntEnum类,我可以很容易地进行比较。但我希望值是字符串,并根据声明顺序比较它们。

h7appiyu

h7appiyu1#

您可以使用__members__字段,它提供member name: member的有序Map,其中的顺序对应于枚举成员的定义顺序(或声明顺序,如您所称)。因此,在您的情况下,它可能看起来如下所示:

class MyEnum(Enum):
    ONE = "one",
    TWO = "two",
    THREE = "three"

    def __le__(self, other):
        members = list(MyEnum.__members__.values())
        return members.index(self) <= members.index(other)
        # Or, equivalently:
        # names = list(MyEnum.__members__.keys())
        # return names.index(self.name) <= names.index(other.name)

请注意,我们比较了有序成员列表中的 indices(或者,等价地,在它们的名称列表中)。这提供了一个通用的解决方案,唯一的假设是我们以所需的顺序定义了我们的成员(ONETWOTHREE)-它们的实际值和类型无关紧要。

编辑:您可能会使用_member_names_字段来达到相同的目的,就像在this answer to a related question中所做的那样;但是,官方文档没有提到这个替代字段,因此可能应该将其视为无法依赖的实现细节。

anauzrmj

anauzrmj2#

您可以使用enum.auto()函数根据字符串枚举值的声明顺序自动为它们生成整数值。这样,您就可以根据这些整数值定义比较方法,而不必两次列出枚举值。

from enum import Enum, auto
from functools import total_ordering

@total_ordering
class MyEnum(Enum):
    ONE = auto()
    TWO = auto()
    THREE = auto()

    def __eq__(self, other):
        if not isinstance(other, MyEnum):
            return False
        return self.value == other.value

    def __lt__(self, other):
        if not isinstance(other, MyEnum):
            return NotImplemented
        return self.value < other.value

另外,class MyEnum(str, Enum):会使枚举值类型为字符串。

omjgkv6w

omjgkv6w3#

您可以直接访问枚举字段的名称:

from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

print(Color.RED) ## Color.RED
print(Color.RED.name) ## RED
print(Color.RED.value) ## 1

希望有帮助!

yhuiod9q

yhuiod9q4#

基于Planet()示例,我可以尝试:

import enum

class MyEnum(enum.Enum):
    ONE = ("one", 1)
    TWO = ("two", 2)
    THREE = ("three", 3)

    def __init__(self, value, ordering):
        self._value_ = value
        self.ordering = ordering

    def __lt__(self, other):
        if self.__class__ is other.__class__:
            return self.ordering < other.ordering

print(MyEnum.ONE)
print(MyEnum.ONE.value)
print(MyEnum.ONE.name)
print(MyEnum.TWO < MyEnum.THREE)

我想这会给予你:

MyEnum.ONE
one
ONE
True

相关问题