5

私はいくつかの Python プロジェクトで列挙型をエミュレートするために小さなクラスを使用してきました。より良い方法はありますか、それとも状況によってはこれが最も理にかなっていますか?

クラスコードはこちら:

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)
4

6 に答える 6

5

列挙型は以前に言語に含めることが提案されていましたが、拒否されました ( http://www.python.org/dev/peps/pep-0354/を参照)。ただし、独自の実装を作成する代わりに使用できる既存のパッケージがあります。 :

于 2008-09-20T15:51:51.080 に答える
4

最も一般的な列挙型のケースは、State または Strategy デザイン パターンの一部である列挙値です。列挙型は、使用される特定の状態または特定のオプションの戦略です。この場合、ほとんどの場合、それらはクラス定義の一部です。

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 )
于 2008-09-20T17:32:17.313 に答える
3

私がより頻繁に目にするのは、トップレベルのモジュール コンテキストで次のようなものです。

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

それに加えて、あなたが提案するクラスに関して私のPythonicの感性を怒らせるもう1つのことは、の使用ですsplit()。タプル、リスト、またはその他の列挙可能なものを最初に渡さないのはなぜですか?

于 2008-09-20T15:58:02.890 に答える
3

ここには良い議論がたくさんあります。

于 2008-09-20T15:58:10.067 に答える
2

列挙型を行う組み込みの方法は次のとおりです。

(FOO, BAR, BAZ) = range(3)

これは小さなセットでは問題なく機能しますが、いくつかの欠点があります。

  • 手で要素の数を数える必要があります
  • 値をスキップすることはできません
  • 名前を 1 つ追加する場合は、範囲番号も更新する必要があります

Python での完全な列挙型の実装については、http: //code.activestate.com/recipes/67107/を参照してください。

于 2008-09-20T15:52:20.063 に答える
1

私は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
于 2009-03-23T18:28:48.477 に答える