web-dev-qa-db-ja.com

文字列をpython enumと比較する方法は?

python)の Enum 基本クラスの存在を発見したばかりで、それがどのように役立つか想像しようとしています。

信号機の状態を定義するとしましょう:

_from enum import Enum, auto

class Signal(Enum):
    red = auto()
    green = auto()
    orange = auto()
_

プログラムのサブシステムから、色の名前を表す文字列形式の情報、たとえば_brain_detected_colour = "red"_を受け取ったとしましょう。

この文字列を信号機の信号と比較するにはどうすればよいですか?

_brain_detected_colour is Signal.red_は文字列ではないため、明らかに_Signal.red_はFalseです。

Signal(brain_detected_colour) is Signal.redは_ValueError: 'red' is not a valid Signal_で失敗します。

23
bli

Enumのインスタンス を作成しません。 Signal(foo)構文は、値によってEnumメンバーにアクセスするために使用されます。これは、auto()である場合に使用されることを意図していません。

ただし、角括弧を使用してdictの値にアクセスするように、文字列を使用して Enumメンバにアクセス を使用できます。

_Signal[brain_detected_colour] is Signal.red
_

別の可能性は、文字列をEnumメンバーのnameと比較することです:

_# Bad practice:
brain_detected_colour is Signal.red.name
_

ただし、ここでは、Enumメンバー間のIDをテストするのではなく、文字列を比較するため、同等性テストを使用することをお勧めします。

_# Better practice:
brain_detected_colour == Signal.red.name
_

(文字列間の同一性比較は string interning のおかげで機能しましたが、これは頼らない方が良いです。@ mwchaseと@Chris_Randsに私に知らせてくれてありがとう。)

さらに別の可能性は、Enumを作成するときに、メンバー値を名前として明示的に設定することです。

_class Signal(Enum):
    red = "red"
    green = "green"
    orange = "orange"
_

(これを自動化する方法については this answer を参照してください。)

次に、Signal(brain_detected_colour) is Signal.redが有効になります。

30
bli

auto()がその値として列挙メンバーの名前を返すようにすることは可能です(これはドキュメントの autoセクションにあります1

>>> class AutoName(Enum):
...     def _generate_next_value_(name, start, count, last_values):
...         return name
...

>>> class Ordinal(AutoName):
...     NORTH = auto()
...     SOUTH = auto()
...     EAST = auto()
...     WEST = auto()
...

>>> list(Ordinal)
[<Ordinal.NORTH: 'NORTH'>, <Ordinal.SOUTH: 'SOUTH'>, <Ordinal.EAST: 'EAST'>, <Ordinal.WEST: 'WEST'>]

1 これにはバージョンPython 3.6、またはaenum 2.0が必要です2 (aenumは2.7以前のPythonで動作します)。

2 開示:私は Python stdlib Enumenum34バックポート 、および 高度な列挙(aenum ライブラリ。

10
Ethan Furman