如何比较 Python 中的枚举?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39268052/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to compare Enums in Python?
提问by Sebastian Werk
Since Python 3.4, the Enum
class exists.
从 Python 3.4 开始,Enum
该类就存在了。
I am writing a program, where some constants have a specific order and I wonder which way is the most pythonic to compare them:
我正在编写一个程序,其中一些常量具有特定的顺序,我想知道哪种方式最适合比较它们:
class Information(Enum):
ValueOnly = 0
FirstDerivative = 1
SecondDerivative = 2
Now there is a method, which needs to compare a given information
of Information
with the different enums:
现在有一种方法,需要将给定的information
ofInformation
与不同的枚举进行比较:
information = Information.FirstDerivative
print(value)
if information >= Information.FirstDerivative:
print(jacobian)
if information >= Information.SecondDerivative:
print(hessian)
The direct comparison does not work with Enums, so there are three approaches and I wonder which one is preferred:
直接比较不适用于 Enum,所以有三种方法,我想知道哪一种是首选:
Approach 1: Use values:
方法一:使用值:
if information.value >= Information.FirstDerivative.value:
...
Approach 2: Use IntEnum:
方法 2:使用 IntEnum:
class Information(IntEnum):
...
Approach 3: Not using Enums at all:
方法 3:根本不使用枚举:
class Information:
ValueOnly = 0
FirstDerivative = 1
SecondDerivative = 2
Each approach works, Approach 1 is a bit more verbose, while Approach 2 uses the not recommended IntEnum-class, while and Approach 3 seems to be the way one did this before Enum was added.
每种方法都有效,方法 1 有点冗长,而方法 2 使用不推荐的 IntEnum 类,而方法 3 似乎是添加 Enum 之前的方法。
I tend to use Approach 1, but I am not sure.
我倾向于使用方法 1,但我不确定。
Thanks for any advise!
感谢您的任何建议!
采纳答案by nigel222
I hadn'r encountered Enum before so I scanned the doc (https://docs.python.org/3/library/enum.html) ... and found OrderedEnum (section 8.13.13.2) Isn't this what you want? From the doc:
我之前没有遇到过 Enum,所以我扫描了文档(https://docs.python.org/3/library/enum.html)......并找到了 OrderedEnum(第 8.13.13.2 节)这不是你想要的吗? 从文档:
>>> class Grade(OrderedEnum):
... A = 5
... B = 4
... C = 3
... D = 2
... F = 1
...
>>> Grade.C < Grade.A
True
回答by juanpa.arrivillaga
You should always implement the rich comparison operaters if you want to use them with an Enum
. Using the functools.total_ordering
class decorator, you only need to implement an __eq__
method along with a single ordering, e.g. __lt__
. Since enum.Enum
already implements __eq__
this becomes even easier:
如果您想将它们与Enum
. 使用functools.total_ordering
类装饰器,您只需要实现一个__eq__
方法以及一个排序,例如__lt__
. 由于enum.Enum
已经实现,__eq__
这变得更加容易:
>>> import enum
>>> from functools import total_ordering
>>> @total_ordering
... class Grade(enum.Enum):
... A = 5
... B = 4
... C = 3
... D = 2
... F = 1
... def __lt__(self, other):
... if self.__class__ is other.__class__:
... return self.value < other.value
... return NotImplemented
...
>>> Grade.A >= Grade.B
True
>>> Grade.A >= 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: Grade() >= int()
Terrible, horrible, ghastly things can happen with IntEnum
. It was mostly included for backwards-compatibility sake, enums used to be implemented by subclassing int
. From the docs:
可怕的,可怕的,可怕的事情可能会发生IntEnum
。它主要是为了向后兼容而包含的,枚举过去是由子类实现的int
。从文档:
For the vast majority of code, Enum is strongly recommended, since IntEnum breaks some semantic promises of an enumeration (by being comparable to integers, and thus by transitivity to other unrelated enumerations). It should be used only in special cases where there's no other choice; for example, when integer constants are replaced with enumerations and backwards compatibility is required with code that still expects integers.
对于绝大多数代码,强烈建议使用 Enum,因为 IntEnum 打破了枚举的一些语义承诺(通过与整数进行比较,从而通过传递到其他不相关的枚举)。它应该只在没有其他选择的特殊情况下使用;例如,当整数常量被枚举替换并且需要向后兼容仍然需要整数的代码时。
Here's an example of why you don't want to do this:
以下是您不想执行此操作的原因的示例:
>>> class GradeNum(enum.IntEnum):
... A = 5
... B = 4
... C = 3
... D = 2
... F = 1
...
>>> class Suit(enum.IntEnum):
... spade = 4
... heart = 3
... diamond = 2
... club = 1
...
>>> GradeNum.A >= GradeNum.B
True
>>> GradeNum.A >= 3
True
>>> GradeNum.B == Suit.spade
True
>>>
回答by He Zhu
My way to implement it is a little different. Just go to source code enum.py and find the class definition of Enum, then add following source codes:
我实现它的方式有点不同。只需到源代码 enum.py 中找到 Enum 的类定义,然后添加以下源代码:
def __gt__(self, other):
if self.value > other.value:
return True
return False
# 2020/03/18 Naive Implementations of He Zhu
def __lt__(self, other):
if self.value < other.value:
return True
return False
# 2020/03/18 Naive Implementations of He Zhu
def __ge__(self, other):
if self.value >= other.value:
return True
return False
# 2020/03/18 Naive Implementations of He Zhu
def __le__(self, other):
if self.value <= other.value:
return True
return False
def __eq__(self, other):
return self.value == other.value
Then, your Python will support na?ve Enum Type Comparison
然后,您的 Python 将支持天真的 Enum 类型比较