ページへ戻る
− Links
印刷
Python/列挙型
の編集 ::
NJF Wiki
xpwiki
:
Python
/
列挙型
の編集
Python/列挙型 の編集
詳細な入力項目を表示
ページタイトル
( 空白で自動設定 )
:
ページ並び順
( 0-9 小数可 標準:1 )
:
ページ別名
(複数は[
改行
]で区切る)
:
ページ内容:
*基本 [#oda99e39] Pythonの列挙型enumは何かひとまとまりの定数を定義するときに便利な型で、Python3.4から導入されました。 例えば、ゲームのプログラムで今どの画面かを識別するために以下のような変数を定義したとします。 SCREEN_TITLE = 1 #タイトル画面 SCREEN_PLAYING = 2 #プレイ中画面 SCREEN_GAME_OVER = 3 #ゲームオーバー画面 SCREEN_TRANSITION = 4 #画面遷移中 このままでもプログラムできますが、もう少しまとめてあつかいたい、と考える人もいるでしょう。 また、ただの変数なのでうっかり書きかえないかも心配です。 これをenumを使えば、以下のように書き直せます。 from enum import Enum class Screen(Enum): TITLE = 1 PLAYING = 2 GAME_OVER = 3 TRANSITION = 4 使う時は Screen.PLAYING などとすれば参照できます。 比較するときはメンバー同士で行う必要があります。 print(Screen.TITLE == 1) print(Screen.TITLE == Screen.TITLE) 結果: False True Enumは他の型の値と直接比較できないので注意してください。 めんどうなようですが、こうなっているとせっかく定義したEnum型を使わずに手で直接値を指定してしまうという、いわゆるマジックナンバーの問題をある程度予防してくれるというメリットがあります。 必要であれば、後述のIntEum型なら整数との比較が可能です。 この記事では数値で定義しましたが、文字列で定義することも可能です。 また、これらは実質定数として扱えます。 例えば、 Screen.GAME_OVER = 2 とすると Traceback (most recent call last): File "enumtest.py", line 10, in <module> Screen.GAME_OVER = 2 File "/usr/lib/python3.6/enum.py", line 363, in __setattr__ raise AttributeError('Cannot reassign members.') AttributeError: Cannot reassign members. というような実行時エラーが出ます。 また、 screen = Screen.PLAYING print(screen) とすると、 Screen.PLAYING とクラスとメンバー名が出力されるのでデバッグの時にわかりやすくて便利です。 nameとvalueというプロパティを使えばメンバー名と値も参照できます。 print(Screen.GAME_OVER.name,Screen.GAME_OVER.value) 結果: GAME_OVER 4 ループ処理もできます。 このとき、順番は定義順であることが保証されています。 for s in Screen: print(s) 結果: Screen.TITLE Screen.PLAYING Screen.GAME_OVER Screen.TRANSITION となります。 このようにenumを使うと定数をまとめてあつかいやすくなります。 さらに以下のような便利な機能があります。 *auto [#kfebf26b] Python3.6から自動で番号をつけてくれるautoという関数が加わりました。 from enum import Enum, auto class Screen(Enum): TITLE = auto() PLAYING = auto() GAME_OVER = auto() TRANSITION = auto() とすれば自動で番号をつけてくれます。 例えば上の例でタイトル画面の前にというロード画面を付け加えたい、順番的にできればそれを表す定数は1にしたい、となったときに、手で番号をつけると今までの定義を全て手で1ずらさねばなりません。 class Screen(Enum): LOADING = 1 TITLE = 2 #ここから下全て1ずらした PLAYING = 3 GAME_OVER = 4 TRANSITION = 5 enumのメンバー数が多いと編集が大変になります。 autoを使っておけば自動で番号をつけてくれるので「LOADING = auto()」という一行を付け加えるだけでよく、手間が省けます。 class Screen(Enum): LOADING = auto() #この行だけ増やした TITLE = auto() PLAYING = auto() GAME_OVER = auto() TRANSITION = auto() また、enum型は値が一意になる事は保証していません。 次のようなコードは問題なく実行されます。 class Test(Enum): TEST1 = 1 TEST2 = 1 TEST3 = 1 しかし、実際には一意な値をつけたいときが多いでしょう。 手で定義するとどうしても書き間違いの可能性が出てきます。 その時は「@unique」というデコレータを使えば一意であることが保証されます。 @unique class Test(Enum): TEST1 = 1 TEST2 = 1 TEST3 = 1 とすると、実行時エラーになります。 しかし、autoを使っておけば、自動的に値は一意になります。 とりあえず値はなんでもいいという場合にはautoを使うのがおすすめです。 autoを使いつつ、特定の値を同じにしたければ以下のようにします。 class Test(Enum): TEST1 = auto() TEST2 = auto() TEST3 = auto() TEST2_ALT = TEST2 print(Test.TEST2_ALT,Test.TEST2_ALT.value) 結果: Test.TEST2 2 *派生列挙型 [#ocba7d30] **IntEnum [#t17d8986] Enumとほぼ同じですが、整数や他のIntEnum型との直接の比較が可能になっています。 ほとんどの場合Enumで十分ですが、外部から入力された値に名前をつけたい、他のプログラムとデータのやり取りをするときに独自の名前をつけたい、計算結果に名前をつけたい、といった場合に、その値が整数なら簡単に比較できるようになるので便利です。 **IntFlagとFlag [#k4589686] Enumにビット演算子を適用可能にしてフラグとして使いやすくした物です。 ここに書くと長くなるのでページを分けて[[Python/FlagとIntFlag]]で説明しています。 *まとめ [#a8d5981a] 列挙型は使わないでもプログラムは書けますし、実際Python3.4までは実装されていませんでしたが、そのころもさほど問題ではありませんでした。 しかし、覚えておくといろいろ便利に使えます。 特に状態遷移などがあり多くの定数が必要なプログラムを書く場合や、Javaなどで列挙型に慣れている人などにはおすすめです。
編集の要約:
Q & A 認証:
ページ更新時は次の質問にお答えください。(プレビュー時は必要ありません)
Q:
「名古屋」の読みがな?(ひらがなで)
A:
お名前:
タイムスタンプを変更しない
テキスト整形のルールを表示する
[1]
添付ファイル
[2]
:
Links list
(This host) = https://njf.jp
(This host)
/cms/modules/xpwiki/?cmd=edit&help=true&page=Python%2F%E5%88%97%E6%8C%99%E5%9E%8B
(This host)
/cms/modules/xpwiki/?plugin=attach&pcmd=list&refer=Python%2F%E5%88%97%E6%8C%99%E5%9E%8B