ツールを作っていると、複数のフラグを扱う事よくありますよね!例えばこんな感じ。
flagA = False flagB = True flagC = False
または、配列を使って1つにまとめる場合もあると思います!
flags = [False, True, False]
でも、コレ「2進数の性質」を使うと1つの数値で管理することができるんです!!(`・ω・´)ゞ
2進数って?
普段使っている数値は、「0~9」の10種類の数字を使って数値を扱っていますね!2進数になると、「0と1」の2個の数字を使って数値を扱います!
と入ってもよくわからないと思うので、表にしています!(`・ω・´)ゞ
10進数 | 2進数 |
---|---|
0 | 0 |
1 | 1 |
2 | 10 |
3 | 11 |
4 | 100 |
5 | 101 |
6 | 110 |
7 | 111 |
8 | 1000 |
9 | 1001 |
10 | 1010 |
2進数は、10進数の「0」「2」「4」「8」「16」の時に桁が増えていきます!頻度が多いですね(;´∀`)
あれ?
2,4,8、16ってどこかで
見たことある並び。。。
そう!CGでもよく出てくる、「2の乗数」で桁が増えていきます!試しに、128までやってみると以下のようになります(*´ω`*)b
10進数 | 2進数 |
---|---|
0 (2の0乗) | 0 |
2 (2の1乗) | 10 |
4 (2の2乗) | 100 |
8 (2の3乗) | 1000 |
16 (2の4乗) | 10000 |
32 (2の5乗) | 100000 |
64 (2の6乗) | 1000000 |
128 (2の7乗) | 10000000 |
あえて右寄せにしましたが、2進数が1桁1桁スイッチのように見えませんか!?例えば、10進数の「8」の場合、、、
更に面白いのが足し算、引き算です(゚∀゚)
10進数の「8+2=10」ですが、2進数の場合は「1000+10=1010」になります。これをまたスイッチの画像にすると、、、
「2の乗数」だけで数値を作ると、1つの数値に「たっくさーーーーーーーーーんのフラグ」を埋め込めることができるんです!!(*´ω`*)
他にも、データ量が少なくて済んだり、計算が早かったりします。
でも、一番の目的は、配列を使うことなく「一つのデータに複数の情報を詰め込める」ことにあると思います(`・ω・´)ゞ
Pythonでの実装!
手順として重要なのは3つの要素です。
- フラグを定義
- フラグの建て方
- フラグの検出
この3つの要素を順番に見ていきたいと思います!(`・ω・´)ゞ
フラグを定義
フラグの定義は、Pythonの場合は「モジュールのグローバル変数」か、「クラス変数」にするといいと思います!
モジュールのグローバル変数の場合
# モジュールのグローバル変数の場合 # 10進数を使って定義する場合 ITEM_FLAG_A = 1 ITEM_FLAG_B = 2 ITEM_FLAG_C = 4 ITEM_FLAG_D = 8 # 2進数を使って定義する場合(頭に「0b」をつけて定義します) ITEM_FLAG_A = 0b1 ITEM_FLAG_B = 0b10 ITEM_FLAG_C = 0b100 ITEM_FLAG_D = 0b1000 # クラス変数の場合 class Item(object): ITEM_FLAG_A = 1 ITEM_FLAG_B = 2 ITEM_FLAG_C = 4 ITEM_FLAG_D = 8
フラグの建て方
次は、変数の数値にフラグをONにしたり、OFFにしたりする方法です。Pythonでは「ビット演算」を使って行います(`・ω・´)ゞ
直接数値を使わず、フラグの定義をした変数を使って計算することをオススメします!あとで、何のフラグを編集したかすごく見やすいです(*´ω`*)b
# すべてのフラグOFFの変数を定義 flags = 0 # AとBのフラグをONにした変数を定義 flags = ITEM_FLAG_A | ITEM_FLAG_B print flags # CのフラグをONにする flags |= ITEM_FLAG_C print flags # BのフラグをOFF flags -= flags & ITEM_FLAG_B print flags
フラグをONにする時は「|」、フラグをOFFにする場合は「&」を使用します。フラグをOFFにしたい場合だけ、ちょっとややっこしい感じですね(;´∀`)
#ビット演算の場合 flags = 0 flags |= ITEM_FLAG_A print flags #1 flags |= ITEM_FLAG_A print flags # 1 何度やっても問題ない。事前にフラグがONか調べる必要もなし! # 足し算の場合 flags = 0 flags += ITEM_FLAG_A print flags # 1 flags += ITEM_FLAG_A print flags # 2 フラグがズレてしまう。
フラグの検出
フラグの検出は、if分を使って行きます。「&」を使い、2進数から必要な部分だけを取り出しフラグが立っているか確認する感じです!
flags = ITEM_FLAG_A | ITEM_FLAG_C # AのフラグがONか確認 if flags & ITEM_FLAG_A: print 'ITEM_FLAG_A is True' # ITEM_FLAG_A is True # BのフラグがOFFか確認 if not flags & ITEM_FLAG_B: print 'ITEM_FLAG_A is False' # ITEM_FLAG_A is False
忙しいことを理由に、家が荒れてきました、、、orz