読者です 読者をやめる 読者になる 読者になる

フラグのような条件比較にブール演算を利用する

python translate

呼称: ブール演算による条件比較
目的: 条件比較に定数を利用してメンテナンス性を高める
特徴: 条件のグループ化ができて、且つソースコードが読み易くなる
用例: コマンドラインのオプションや設定ファイルの設定項目などに使用する
備考: エキスパート Python プログラミングの第4章「良い名前の選択」-名前付けのスタイル-変数-定数を参照

doctest や re モジュールで使用されている仕組みが紹介されていました。以下は doctest のオプション設定の部分ですが register_optionflag() を使用してグローバルな OPTIONFLAGS_BY_NAME の辞書に各オプションの値をセットしています。セットされる値は 1 bit ずつシフトされた値がセットされているので、オプションの組み合わせに対する条件比較がブール演算で可能になります。

$ vi /usr/lib/python2.6/doctest.py
...
127 OPTIONFLAGS_BY_NAME = {}
128 def register_optionflag(name):
129     # Create a new flag unless `name` is already known.
130     return OPTIONFLAGS_BY_NAME.setdefault(name, 1 << len(OPTIONFLAGS_BY_NAME))
131 
132 DONT_ACCEPT_TRUE_FOR_1 = register_optionflag('DONT_ACCEPT_TRUE_FOR_1')
133 DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE')
134 NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE')
...

実際にファイルの拡張子を入力してファイルの種類を判断するサンプルを作ってみました。メンテナンス性を高める目的で、条件比較に辞書をよく使用していたのですが、キーに対する値に意味がない(ただ分かり易い文字列で条件比較したいだけ)場合はブール演算ができる値をセットしておくと良いかもしれません。

#!/usr/bin/env python

import sys
import signal

FILE_TYPE = {
    'unk': 1 << 0,
    'txt': 1 << 1,
    'eml': 1 << 2,
    'rst': 1 << 3,
    'jpg': 1 << 4,
    'png': 1 << 5,
    'bmp': 1 << 6,
    'doc': 1 << 7,
    'xls': 1 << 8,
    'ppt': 1 << 9,
}

FILE_TXT_TYPE = FILE_TYPE['txt'] | FILE_TYPE['eml'] | FILE_TYPE['rst']
FILE_IMG_TYPE = FILE_TYPE['jpg'] | FILE_TYPE['png'] | FILE_TYPE['bmp']
FILE_OFC_TYPE = FILE_TYPE['doc'] | FILE_TYPE['xls'] | FILE_TYPE['ppt']

def main():
    signal.signal(signal.SIGINT, lambda *args: sys.exit())
    while True:
        type = FILE_TYPE.setdefault(raw_input(), FILE_TYPE['unk'])
        if type & FILE_TXT_TYPE:
            print 'It is Text File'
        elif type & FILE_IMG_TYPE:
            print 'It is Image File'
        elif type & FILE_OFC_TYPE:
            print 'It is Office File'
        else:
            print 'It is Unknown File'

if __name__ == '__main__':
    main()

実行結果。

$ python bool_operation.py 
txt
It is Text File
jpg
It is Image File
jpeg
It is Unknown File
xls
It is Office File
detarame
It is Unknown File
^C

ブール値を扱いたいときは組み込み関数の bool() を使用することで True or False が取得できます。

result = bool(type & FILE_TXT_TYPE)

リファレンス:
23.2 doctest -- 対話モードを使った使用例の内容をテストする
4.2 re -- 正規表現操作
2.3.10.9 ブール値