2011-08-12 3 views
7

長い間、私は、Python関数にフラグを渡す最も良い方法が何であるか把握しようとしています。最も簡単な方法のようなものです:Python:関数にフラグを渡す

def func(data, flag1, flag2, flag3): 
    ... 

func(my_data, True, False, True) 

これは、単語「true」または「false」があなたに設定されているもののフラグについて何も伝えないので、本当に素晴らしく、簡潔な、しかし、読み非常に難しいです、そしてあなた左から始まる議論を注意深く数えなければならない。

def func(data, flag1=False, flag2=False, flag3=False): 
    ... 

func(my_data, flag1=True, flag3=True) 

が、これは冗長なの一種である、「真」以来まったく意味を運ばない:あなたはそれらのキーワード引数を作ることができます。私はそれをリストとして渡すことができます。

func(mydata, ['flag1', 'flag3']) 

または

func(mydata, [func.flag1, func.flag3]) 

しかし、最初はフラグとして文字列を使用して、かなり汚い感じている、第二は、まだ多少の繰り返しです。最小限の冗長性と冗長性を備えた関数にフラグを渡すために

func(my_data, flag1, flag3) 

:理想的には私のような何かを言いたいです。このようなPythonで何かをする方法はありますか?

EDIT: 一緒に行くことになったI:グローバル「ENUM」のを使用するのではなく、コンパイル時(文字列を渡し対)をチェック、ノー名前空間の汚染(:主に述べた理由のため

func(mydata, flagA=1, flagB=1) 

)と最小限の定型文(= 1または= 0は2文字のみです。= 5または6は= Trueまたは= Falseです)。また、非常に簡単にフラグのデフォルト値を設定します:はるかに明確かつに** kwargスタイルのフラグを抽出し、デフォルト値を割り当てるためにフープを介してジャンプするよりもはるかに簡単です

def func(data, flagA=1, flagB=0, flagC=1): 
    ... 

を。フラグは基本的には静的にチェックされ、非常にクリア/クリーンに書き込まれます。今、私は最後の2つの文字を剃り落とすことができた場合にのみ... *引数付き

+1

は、なぜあなたは/が最初の場所でのフラグを渡す必要がありたいですか?おそらくあなたはあなたのインターフェースを考え直すべきです... –

+0

フラグは、データ構造内で動作する関数の将来の動作を制御するデータ構造内のboolを設定するために使用されます。これは完全に非OOのアプローチですが、私は簡単に選択しました。たとえ私がOOスタイルにしても、行動の変化はかなり微妙で、扱うクラスのファミリー全体を作成する価値がないかもしれません。 –

+0

おそらく、値を含む(より単純な)データ構造を渡すことができますか?フラグのセット、またはboolにフラグ名をマップする 'dict' ... –

答えて

3

いくつかのPythonの標準ライブラリはこれを使用する:

re.match(pattern, str, re.MULTILINE | re.IGNORECASE) 

あなたは*引数を使用して、このアプローチを微調整することができます

my.func(a, b, c, my.MULTLINE, my.IGNORECASE) 

私は本当にFLAG1 =真と一緒に行くお勧めします:

  • 可読です
  • コンパイル時にフラグ名がチェックされています時間
  • あなたは長い名前を再入力せず
  • あなたは一時的にFalseにLONG_FLAG_NAME_YOU_DONT_REMEMBER = trueを変更することができ、ノイズを低減する代わりに、TrueとFalseのフラグ= 1、フラグ= 0を使用することができます(** kwargsからしない限り、使用されている)とき変更する必要があります
3

def some_func(data, *args): 
    # do something 
    return args # this is just to show how it works 


>>> print some_func(12, 'test', 'test2', 'test3') 
('test', 'test2', 'test3') 

これはkwargsからはどのように動作するか*引数と**理解する良い質問です:*args and **kwargs?

5

あなたは、グローバル変数としてflag1 ... flagNを定義し、definiによってfunc(*args)

FLAG1 = 1 
FLAG2 = 2 

def func(*args): 
    pass 

func(FLAG1, FLAG2) 

であなたの関数を定義することができますフラグを別に使用する代わりに、フラグを使用する代わりに、デバッグ時にフラグの名前や頭痛のタイプを避けることができます。

-1

むしろこれを行う:

def func_flag1(arg): 
    pass # something useful 

def func_flag2(arg): 
    pass # something for flag 2. 

しかし、 "flagXが" 実際に "do_X_with_option" のような意味のあるものになるだろう。

これは、関数をよりシンプルに(バグの少ない)、他のモジュールにいくつかの定数を渡す必要がないためです(実際には何らかの列挙型の場合)。

+0

問題は私のフラグが独立していることです。したがって、O(n)フラグを取るとO(2^n)個の関数がエミュレートされます。私は現在2つのフラグを持っています。これは4つの関数を取ります.3つまたは4つのフラグについても素早く手を出せません。 –

3

それを反転させるのはどうですか?

flag1, flag2, flag3, flag4, flag5, flag6 = range(6) 

def func(enable=[], disable=[], 
     enabled_by_default=[flag5, flag6]): 
    enabled = set(enabled_by_default + enabled) - set(disabled) 
    if flag1 in enabled: 
     ... 
    if flag2 in enabled: 
     ... 

func(enable = [flag1, flag2, flag3], 
    disable = [flag6]) 
私は古き良き bitwiseフラグ行方不明です
3

a = 1 
b = 2 
c = 4 
d = 8 

def func(data, flags): 
    print((flags & a) == a) 
    print((flags & b) == b) 
    print((flags & c) == c) 
    print((flags & d) == d) 

>>>> func("bla", a|c|d) 
>>>> True 
>>>> False 
>>>> True 
>>>> True 
+0

ありがとうございます。私は30分、 "python bit flags"についてgoogleを検索しました。 – Arne

関連する問題