ページへ戻る
− Links
印刷
Python/FlagとIntFlag
の編集 ::
NJF Wiki
xpwiki
:
Python
/
FlagとIntFlag
の編集
Python/FlagとIntFlag の編集
詳細な入力項目を表示
ページタイトル
( 空白で自動設定 )
:
ページ並び順
( 0-9 小数可 標準:1 )
:
ページ別名
(複数は[
改行
]で区切る)
:
ページ内容:
*Flag [#h3172853] ''注意'':FlagやIntFlagは列挙型Enumの一種です。Enumを知らない場合は[[Python/列挙型]]を先に読むのを推奨します。 昔からあるプログラムの書き方で、ビット毎にフラグを設定して一つの変数に複数のフラグを保存する方法があります。 ビット単位で管理するのでメモリが節約できます。また一般にビット演算は高速なのでプログラムの高速化も狙えます。 これと同じようなことを実現するPythonのクラスがFlagです。 例えば、ゲームで状態異常を定義したいとして、次のようなクラスを定義します。 from enum import Flag class PlayerStatus(Flag): SLEEP = 1 #睡眠 POISON = 2 #毒 PARALYSIS = 4 #麻痺 ここで1,2,4は二進数で書けば1,10,100の事で、それぞれ1ビット目、2ビット目,3ビット目をフラグとして使っています。 このように手で書くこともできますが、Python3.6で追加されたautoという関数を使うと自動で二のべき乗を割り振ってくれます。 from enum import Flag ,auto class PlayerStatus(Flag): SLEEP = auto() POISON = auto() PARALYSIS = auto() for s in PlayerStatus: print(s.name,s.value) 結果: SLEEP 1 POISON 2 PARALYSIS 4 これの良いところは一つの変数に複数のフラグを設定できることです。 例えば、睡眠かつ毒状態のステータスは status = PlayerStatus.SLEEP | PlayerStatus.POISON と書きます。これを表示させると、 print(status) 結果: PlayerStatus.POISON|SLEEP というふうに、実際にフラグが複数設定されています。 また、Flag型はフラグの状態をわかりやすく出力してくれるのでデバッグの時便利です。 フラグが立っているかどうかは「&」でチェックします。 status = PlayerStatus.SLEEP | PlayerStatus.POISON if status & PlayerStatus.SLEEP: print("SLEEP!") if status & PlayerStatus.POISON: print("POISON!") if status & PlayerStatus.PARALYSIS: print("PARALYSIS!") 結果: SLEEP! POISON! フラグをオフにするには以下のように「&」と「~」(否定)を組み合わせます。 status = PlayerStatus.SLEEP | PlayerStatus.POISON status = PlayerStatus.SLEEP & (~PlayerStatus.POISON) if status & PlayerStatus.SLEEP: print("SLEEP!") if status & PlayerStatus.POISON: print("POISON!") if status & PlayerStatus.PARALYSIS: print("PARALYSIS!") 結果: POISON! また、Flag型はFlag型同士でなければ演算できないことに注意してください。 Intと演算したいときには次のIntFlag型を使います。 *IntFlag [#d713d3b4] IntFlag型はFlag型とほぼ同じ機能がありますが、Flag型とは異なり整数としても扱えます。 つまり、Flag型では次の処理はエラーとなります。 status = PlayerStatus.SLEEP | 2 print(status) Flag型での結果: Traceback (most recent call last): File "enumflgs.py", line 50, in <module> status = PlayerStatus.SLEEP | 2 TypeError: unsupported operand type(s) for |: 'PlayerStatus' and 'int' しかし、IntFlag型なら問題なく実行されます。 IntFlag型での結果: PlayerStatus.POISON|SLEEP 直接数値が使えないのでFlag型の方がマジックナンバーが発生しにくいという利点があります。 一方でIntFlag型は計算結果や外部入力の数値をそのままフラグとして演算できるという利点があります。 基本的にFlag型を使い、フラグを整数と演算する必要がある場合はIntFlag型を使うというのが良いかもしれません。 *まとめ [#peb2d989] Flagはビット演算でのフラグの管理を使いやすくするクラスです。 IntFlagはそのFlagを整数としても扱えるようにした物です。 フラグがたくさんあって整理が難しい場合や、少しでも処理を高速化したい場合には便利なクラスです。 ただし、現在のようにメモリも大容量でCPUも速くなった時代にフラグ処理が少し軽くなる程度の工夫が必要かどうかはちょっと微妙な気もします。特にPythonのようなスクリプト言語は他の部分が遅いのでフラグがボトルネックにはなりにくく、ビットフラグをよく使うのはCなどのコンパイル言語というイメージです。そういった言語で使い慣れている人にはFlagやIntFlagは使いやすいでしょう。 フラグが少なく処理が簡単な場合は真偽型boolをそのまま使うか、いくつかまとめたクラスを作って使う方が楽です。
編集の要約:
Q & A 認証:
ページ更新時は次の質問にお答えください。(プレビュー時は必要ありません)
Q:
「名古屋」の読みがな?(ひらがなで)
A:
お名前:
タイムスタンプを変更しない
テキスト整形のルールを表示する
[1]
添付ファイル
[2]
:
Links list
(This host) = https://njf.jp
(This host)
/cms/modules/xpwiki/?cmd=edit&help=true&page=Python%2FFlag%E3%81%A8IntFlag
(This host)
/cms/modules/xpwiki/?plugin=attach&pcmd=list&refer=Python%2FFlag%E3%81%A8IntFlag