2016-09-01 91 views
6

自Python 3.4以來,存在Enum類。如何比較Python中的枚舉?

我寫一個程序,其中一些常量有一個特定的順序,我不知道哪種方式是最Python的對它們進行比較:

class Information(Enum): 
    ValueOnly = 0 
    FirstDerivative = 1 
    SecondDerivative = 2 

現在有一種方法,它需要比較給定informationInformation與不同的枚舉:

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,但我不確定。

感謝您的任何建議!

回答

9

,如果你想與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() 

可怕,可怕,可怕的事情可以發生IntEnum。它主要是爲了向後兼容而包括的,枚舉過去通過子類化int來實現。從docs

對於絕大多數的代碼,枚舉強烈推薦,因爲 IntEnum打破枚舉的一些語義的承諾(通過被 媲美整數,從而通過傳遞給其他不相關 枚舉) 。它只能用於 沒有其他選擇的特殊情況;例如,當整數常量被替換爲 枚舉時,並且 依然期望整數的代碼需要向後兼容性。

這裏就是爲什麼你不想做這樣的一個例子:

>>> 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 
>>> 
+1

很好的描述,非常感謝。只有一個問題:你'返回NotImplemented'而不是'raise NotImplemented'。是否有一條通用規則,何時使用回報和何時加註? –

+2

@SebastianWerk那麼,你不能'提高NotImplemented',因爲它不是一個例外。它是一個內置的單身人士。請參閱[docs](https://docs.python.org/3.5/library/constants.html#NotImplemented),它適用於富比較運算符的特殊情況。在'NotImplementedError',根據[文檔](https://docs.python.org/2/library/exceptions.html#exceptions.NotImplementedError),是有當「抽象方法應該提高該異常時,他們要求衍生類覆蓋該方法。「 」。 –

+2

@SebastianWerk另外,看到這個問題:http://stackoverflow.com/questions/878943/why-return-notimplemented-instead-of-raising-notimplementederror –

0

我hadn'r遇到枚舉之前,所以我掃描文檔(https://docs.python.org/3/library/enum.html)...並找到OrderedEnum(第8.13.13.2節)這不是你想要的?從DOC:

>>> class Grade(OrderedEnum): 
...  A = 5 
...  B = 4 
...  C = 3 
...  D = 2 
...  F = 1 
... 
>>> Grade.C < Grade.A 
True 
+0

我也發現了這張貼的問題後。由於我只需要一點或兩點在我的程序中,我寧願使用價值 - 方法。我想知道這種方式是否會在標準庫中實現。 –