2016-09-01 8 views
6

Python 3.4以降、Enumクラスが存在します。Pythonで列挙型を比較す​​るには?

私はいくつかの定数は、特定の順序を持​​っていると私はそれらを比較するのが最も神託のある方法だろプログラムを書いています:

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

今与えられたを比較する必要がある方法があるinformation異なる列挙型とInformationの:

information = Information.FirstDerivative 
print(value) 
if information >= Information.FirstDerivative: 
    print(jacobian) 
if information >= Information.SecondDerivative: 
    print(hessian) 

は、直接の比較は、列挙型では動作しませんので、3つのアプローチがあると私は1つが優先されるだろう。

アプローチ1:使用値:

if information.value >= Information.FirstDerivative.value: 
    ... 

はアプローチ2:使用IntEnum:

class Information(IntEnum): 
    ... 

アプローチ3:すべての列挙型を使用していない:

class Information: 
    ValueOnly = 0 
    FirstDerivative = 1 
    SecondDerivative = 2 

各アプローチは動作しますが、アプローチアプローチ2は推奨されていないIntEnumクラスを使用し、アプローチ3はEnumが追加される前の方法です。

私はアプローチ1を使用する傾向がありますが、わかりません。

ありがとうございました!

答えて

9

あなたは常に豊富な比較operatersを実装する必要があります。 functools.total_orderingクラスデコレータを使用すると、__eq__メソッドと1つの並べ替えだけを実装する必要があります。 __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

すばらしい説明、ありがとう。あなたは 'raise NotImplemented'の代わりに' NotImplemented'を返します。通常のルールはありますか?いつリターンを使用するのですか? –

+2

@SebastianWerkさて、例外ではないので、NotImplementedを呼び出すことはできません。これはビルトインシングルトンです。 [docs](https://docs.python.org/3.5/library/constants.html#NotImplemented)を参照してください。リッチ比較演算子の特別なケースがあります。 [docs](https://docs.python.org/2/library/exceptions.html#exceptions.NotImplementedError)によると、「NotImplementedError」は、「抽象メソッドは、派生が必要なときにこの例外を発生させるべきときメソッドをオーバーライドするクラス。 "。 –

+2

@SebastianWerkまた、この質問を参照してください:http://stackoverflow.com/questions/878943/why-return-notimplemented-instead-of-raising-notimplementederror –

0

以前はEnumが見つかりませんでしたので、私は文書(https://docs.python.org/3/library/enum.html)をスキャンし、OrderedEnum(8.13.13.2節)を見つけましたか?ドキュメントから:あなたはEnumでそれらを使用したい場合は

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

私も質問を投稿した後、これを見つけました。プログラムの1〜2点でしか必要ないので、私はむしろバリューアプローチを使用したいと思います。この方法がいつか標準ライブラリに実装されるのだろうかと思います。 –

関連する問題