私は、所定の関数が所定の確率で選択されるデータ構造上で動作する関数の集合を持っています。リストに-ing私は、リスト中の各正の整数を割り当てることによって、これを行うitertools.accumulate
は重みを-ing、その後、bisect
:多くの関数の1つに可変数の引数を適用する
func_weights = list(accumulate(weights))
probability = bisect(func_weights, random.random() * func_weights[-1])
問題は、これらの機能のそれぞれがわずかに異なるセットを持っていることを来りますパラメータ/引数。それらの中にはデータ構造だけを必要とするものもあれば、プログラムの残りの部分から追加情報を必要とするものもあります。今、私は辞書へのすべての呼び出しのための追加情報を構築し、私のような各機能を見て持つことができるように、func[probability](data_struct, **arguments)
として関数に渡します。これは十分に機能
funcs = [func_1, func_2, func_3, ...]
weights = [1, 2, 3, ...]
func_weights = list(accumulate(weights))
probability = bisect(func_weights, random.random() * func_weights[-1])
funcs[probability](data_struct, **arguments)
# ...
def func_1(data_s, arg_1, **kwargs):
# blah blah blah
def func_2(data_s, arg_2, **kwargs):
# blah blah blah
def func_3(data_s, arg_1, arg_2, **kwargs):
# blah blah blah
を、と私はかなりスマートに感じました私は最終的にそれがすべて設定しまったが、私はdata_structureを少し変更し、そして今、このからくりの両方の部分を再考えていたとき:
まず、引数のいくつかは、ランダムな数字なので、代わりにすべての関数でrandom.random()を呼び出すと、私は
build_arguments()
で1回呼びます。私はこれを考えたことがありますか?第2に、
**arguments
ではなく、手の込んだスイッチスタイルのステートメントを設定するほうが賢明でしょうか?インデックスに二分し、funcの名前をつかみ、if-then正しい関数を取得します。
例:第三に、点の横に少し
if name == 'func_1':
func_1(data_struct, arg_1)
elif name == 'func_2':
func_2(data_struct, arg_2)
elif name == 'func_3':
func_3(data_struct, arg_1, arg_2)
# etc etc
- 、これらの機能の全ては、代わりに純粋であることの、構造内のデータを直接操作します。 data_structure全体ではなく、変更される要素だけを渡すほうが賢明でしょうか?
例:
data_s[:] = func_3(data_struct.alist, arg_1, arg_2)
# ...
def func_3(alist, arg_1, arg_2, **kwargs):
temp = alist[:arg_1] + alist[arg_2:]
point = random.randint(len(temp))
return temp[:point] + alist[arg_1:arg_2] + temp[point:]
対
func_3(data_struct, arg_1, arg_2)
# ...
def func_3(data_s, arg_1, arg_2, **kwargs):
alist = data_s.alist
temp = alist[:arg_1] + alist[arg_2:]
point = random.randint(len(temp))
data_s.alist[:] = temp[:point] + alist[arg_1:arg_2] + temp[point:]
本当にありがとうございました!
編集:混乱があるようです。私は小さなエラーを修正しましたが、そうでない場合は、in this gist I just createdのように、3.4と3.5の両方で説明したように動作します。
実際に試してみましたか? '** arguments'では、関数に引数をいくつでも渡すことはできません。キーワード引数のみを渡すことができます。 '* arguments'(1つ星)が必要です。 '* arguments'(あるいはもっと一般的には' * args')は実際にはかなりエレガントです。 – jbasko
これはどのように動作するかを示す[gist](https://gist.github.com/NoahTheDuke/6e8c88275c5e743fba971549d8b70759)を投稿しました。二重星( '** args')は辞書をとり、関数の引数にその項目を当てはめ、残りが' 'kwargs''に収まるようにしようとします。 –