如何在Python中比较枚举?
自Python 3.4以来,就存在如何在Python中比较枚举?,python,python-3.x,enums,compare,Python,Python 3.x,Enums,Compare,自Python 3.4以来,就存在Enum类 我正在编写一个程序,其中一些常量有一个特定的顺序,我想知道哪种方式比较它们最为方便: class Information(Enum): ValueOnly = 0 FirstDerivative = 1 SecondDerivative = 2 现在有一种方法,需要将信息的给定信息与不同的枚举进行比较: information = Information.FirstDerivative print(value) if inf
Enum
类
我正在编写一个程序,其中一些常量有一个特定的顺序,我想知道哪种方式比较它们最为方便:
class Information(Enum):
ValueOnly = 0
FirstDerivative = 1
SecondDerivative = 2
现在有一种方法,需要将信息
的给定信息
与不同的枚举进行比较:
information = Information.FirstDerivative
print(value)
if information >= Information.FirstDerivative:
print(jacobian)
if information >= Information.SecondDerivative:
print(hessian)
直接比较不适用于枚举,因此有三种方法,我想知道哪种方法更可取:
方法1:使用价值观:
if information.value >= Information.FirstDerivative.value:
...
方法2:使用IntEnum:
class Information(IntEnum):
...
方法3:根本不使用枚举:
class Information:
ValueOnly = 0
FirstDerivative = 1
SecondDerivative = 2
每种方法都有效,方法1更详细一些,而方法2使用不推荐的IntEnum类,而方法3似乎是添加Enum之前的方法
我倾向于使用方法1,但我不确定
谢谢你的建议 我以前没有遇到过Enum,所以我扫描了文档()。。。找到OrderedEnum(第8.13.13.2节)这不是你想要的吗?从文档:
>>> class Grade(OrderedEnum):
... A = 5
... B = 4
... C = 3
... D = 2
... F = 1
...
>>> Grade.C < Grade.A
True
>等级(OrderedEnum):
... A=5
... B=4
... C=3
... D=2
... F=1
...
>>>C级
如果要将富比较运算符与枚举一起使用,则应始终实现它们。使用functools.total\u ordering
类装饰器,您只需要实现一个\uu eq\uuu
方法和一个单独的排序,例如\uu lt\uuu
。由于enum.enum
已经实现了\uuuuu eq\uuuu
,这就变得更加容易了:
>>> 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()
结合上述一些思想,您可以将enum.enum子类化,使其与字符串/数字相比较,然后在此类上构建枚举:
import numbers
import enum
class EnumComparable(enum.Enum):
def __gt__(self, other):
try:
return self.value > other.value
except:
pass
try:
if isinstance(other, numbers.Real):
return self.value > other
except:
pass
return NotImplemented
def __lt__(self, other):
try:
return self.value < other.value
except:
pass
try:
if isinstance(other, numbers.Real):
return self.value < other
except:
pass
return NotImplemented
def __ge__(self, other):
try:
return self.value >= other.value
except:
pass
try:
if isinstance(other, numbers.Real):
return self.value >= other
if isinstance(other, str):
return self.name == other
except:
pass
return NotImplemented
def __le__(self, other):
try:
return self.value <= other.value
except:
pass
try:
if isinstance(other, numbers.Real):
return self.value <= other
if isinstance(other, str):
return self.name == other
except:
pass
return NotImplemented
def __eq__(self, other):
if self.__class__ is other.__class__:
return self == other
try:
return self.value == other.value
except:
pass
try:
if isinstance(other, numbers.Real):
return self.value == other
if isinstance(other, str):
return self.name == other
except:
pass
return NotImplemented
导入编号
导入枚举
类枚举(enum.enum):
定义(自身、其他):
尝试:
返回self.value>other.value
除:
通过
尝试:
如果isinstance(其他,数字.实数):
返回self.value>other
除:
通过
返回未执行
定义(自身、其他):
尝试:
返回self.value=其他.value
除:
通过
尝试:
如果isinstance(其他,数字.实数):
返回self.value>=其他
如果存在(其他,str):
返回self.name==other
除:
通过
返回未执行
定义(自我、其他):
尝试:
返回自我。价值很好的描述,非常感谢。只有一个问题:您返回NotImplemented
,而不是提出NotImplemented
。什么时候使用return,什么时候使用raise,有没有一般的规则?@SebastianWerk好吧,你不能raisenotimplemented
,因为这不是一个例外。它是一个内置的单体。请参见,这是rich比较运算符的特例。根据,当“抽象方法需要派生类重写该方法时,应引发此异常”时,存在未实现错误。@SebastianWerk还请参见此问题:回答很好,先生。这种方法是一种简洁的方法,虽然效率较低,但可以替代中详述的orderedum
类。虽然手动实现所有比较运算符的orderedum
解决方案速度稍快,但上面给出的@total_ordering
解决方案有其优点。简洁是吃力不讨好的美德。与此相关的是,有人知道为什么OrderedEnum
只是被记录而不是添加到enum
模块中吗?是否有pythonenum
构造或类似的构造实际上有点。。作品添加@total_排序并实现比较运算符并不是我们必须自己编写代码的事情。这是太多的陈词滥调了。你能引用“不推荐的IntEnum类”吗?3.7.1版的文档一点也不反对它。当然,从文档中可以看出:“对于大多数新代码,强烈建议使用Enum和Flag,因为IntEnum和IntFlag破坏了枚举的一些语义承诺(通过与整数相比较,从而传递到其他不相关的枚举).IntEnum和IntFlag仅应在Enum和Flag不起作用的情况下使用;例如,当整数常量替换为枚举时,或用于与其他系统的互操作性。“方法1适合我,谢谢!由于未修复的Python错误,这种方法不起作用:您应该始终覆盖比较器方法,如eq和lt@asu没有未修复的错误,该线程中的问题与Enum
本身无关,而且在任何情况下,该示例都会覆盖比较运算符。在Python 3.6中似乎无法导入,导入错误:无法导入名称“OrderedEnum”
?编辑:看起来这是一个“有趣的示例”,实际上不在标准python库中。您需要从文档中复制代码段才能使用它。
import numbers
import enum
class EnumComparable(enum.Enum):
def __gt__(self, other):
try:
return self.value > other.value
except:
pass
try:
if isinstance(other, numbers.Real):
return self.value > other
except:
pass
return NotImplemented
def __lt__(self, other):
try:
return self.value < other.value
except:
pass
try:
if isinstance(other, numbers.Real):
return self.value < other
except:
pass
return NotImplemented
def __ge__(self, other):
try:
return self.value >= other.value
except:
pass
try:
if isinstance(other, numbers.Real):
return self.value >= other
if isinstance(other, str):
return self.name == other
except:
pass
return NotImplemented
def __le__(self, other):
try:
return self.value <= other.value
except:
pass
try:
if isinstance(other, numbers.Real):
return self.value <= other
if isinstance(other, str):
return self.name == other
except:
pass
return NotImplemented
def __eq__(self, other):
if self.__class__ is other.__class__:
return self == other
try:
return self.value == other.value
except:
pass
try:
if isinstance(other, numbers.Real):
return self.value == other
if isinstance(other, str):
return self.name == other
except:
pass
return NotImplemented