Python で列挙型をエミュレートしたり回避したりするにはどうすればよいでしょうか?[重複]
質問
この質問にはすでに答えがあります:
- Python で「列挙型」を表現するにはどうすればよいですか? 43 件の回答
私はいくつかの Python プロジェクトで Enum をエミュレートするために小さなクラスを使用してきました。もっと良い方法はありますか、それとも状況によってはこれが最も合理的ですか?
ここのクラスコード:
class Enum(object):
'''Simple Enum Class
Example Usage:
>>> codes = Enum('FOO BAR BAZ') # codes.BAZ will be 2 and so on ...'''
def __init__(self, names):
for number, name in enumerate(names.split()):
setattr(self, name, number)
解決
良い議論がたくさんあります ここ.
他のヒント
列挙型は以前にも言語に含めることが提案されましたが、拒否されました (「 http://www.python.org/dev/peps/pep-0354/)、ただし、独自の実装を作成する代わりに使用できる既存のパッケージがあります。
- 列挙型: http://pypi.python.org/pypi/enum
- SymbolType (列挙型とまったく同じではありませんが、それでも便利です): http://pypi.python.org/pypi/SymbolType
- または単に検索してください
最も一般的な列挙型のケースは、状態または戦略の設計パターンの一部である列挙値です。列挙型は、使用される特定の状態または特定のオプションの戦略です。この場合、それらはほとんどの場合、何らかのクラス定義の一部です。
class DoTheNeedful( object ):
ONE_CHOICE = 1
ANOTHER_CHOICE = 2
YET_ANOTHER = 99
def __init__( self, aSelection ):
assert aSelection in ( self.ONE_CHOICE, self.ANOTHER_CHOICE, self.YET_ANOTHER )
self.selection= aSelection
次に、このクラスのクライアントで。
dtn = DoTheNeeful( DoTheNeeful.ONE_CHOICE )
私がよく目にするのは、トップレベルのモジュールのコンテキストで次のようなものです。
FOO_BAR = 'FOO_BAR'
FOO_BAZ = 'FOO_BAZ'
FOO_QUX = 'FOO_QUX'
...以降...
if something is FOO_BAR: pass # do something here
elif something is FOO_BAZ: pass # do something else
elif something is FOO_QUX: pass # do something else
else: raise Exception('Invalid value for something')
の使用に注意してください is
それよりも ==
ここではリスクを冒しています -- 人々が使用していることを前提としています your_module.FOO_BAR
文字列ではなく 'FOO_BAR'
(それは 通常は そのように抑留される is
一致しますが、それは当てにできません)。そのため、コンテキストによっては適切ではない可能性があります。
この方法で行う利点の 1 つは、その文字列への参照が保存されている場所を調べれば、その参照がどこから来たのかがすぐにわかることです。 FOO_BAZ
よりもはるかに曖昧ではありません 2
.
それに加えて、あなたが提案したクラスに関して私の Python 的感性を害するもう 1 つのことは、次の使用です。 split()
. 。まず最初にタプル、リスト、またはその他の列挙型を渡すだけではどうでしょうか?
enum を実行する組み込みの方法は次のとおりです。
(FOO, BAR, BAZ) = range(3)
これは小さなセットではうまく機能しますが、いくつかの欠点があります。
- 要素の数を手動で数える必要があります
- 値をスキップすることはできません
- 名前を 1 つ追加する場合は、範囲番号も更新する必要があります
Python での完全な enum 実装については、以下を参照してください。http://code.activestate.com/recipes/67107/
私は S.Lott の答えによく似たものから始めましたが、列挙型の値を出力して比較できるように (オブジェクト クラス全体ではなく) 'str' と 'eq' のみをオーバーロードしました。
class enumSeason():
Spring = 0
Summer = 1
Fall = 2
Winter = 3
def __init__(self, Type):
self.value = Type
def __str__(self):
if self.value == enumSeason.Spring:
return 'Spring'
if self.value == enumSeason.Summer:
return 'Summer'
if self.value == enumSeason.Fall:
return 'Fall'
if self.value == enumSeason.Winter:
return 'Winter'
def __eq__(self,y):
return self.value==y.value
Print(x) は値の代わりに名前を生成し、Spring を保持する 2 つの値は互いに等しくなります。
>>> x = enumSeason(enumSeason.Spring)
>>> print(x)
Spring
>>> y = enumSeason(enumSeason.Spring)
>>> x == y
True