4

最近Pythonを学び始めたばかりです。私が達成しようとしていることを説明しましょう。基本的にいくつかの関数 (スクリプトにハードコードされている) をすべて 1 つのリストに追加する必要があるこの .py スクリプトがあるため、次のようにインデックス演算子を使用するだけで必要な関数を取得できます。

必要な関数 = 関数リスト[必要な関数のインデックス]

これを実装する最初の試みは、次のコード構造になりました。

(imports)
function_list = []
(other global variables)

def function_0 = (...)
function_list.append(function_0)

def function_1 = (...)
function_list.append(function_1)

def function_2 = (...)
function_list.append(function_2)

(rest of code)

しかし、それはあまりエレガントではないので、私はその解決策が好きではありません。私の目標は、関数定義を (append 呼び出しなしで) スクリプトに単純に追加できるようにすることです。スクリプトはそれを関数のリストに自動的に追加します。

すべての関数を別の関数内で定義することを考えましたが、それらでどこにも到達できないと思います。各関数にデコレータを「タグ付け」することを考えましたが、関数が呼び出されるたびにデコレータ (正しく理解していれば) が呼び出されることに気付きました。

しばらくして、私はこの解決策を思いつきました:

(imports)
(global variables)

def function_0 = (...)

def function_1 = (...)

def function_2 = (...)

function_list= [globals()[x] for x in globals() if re.match('^function_[0-9]+$', x)]

(rest of code)

解決策としてはもう少し気に入っていますが、唯一の問題は、スクリプトの先頭で function_list を完全に定義することを好むということです。ただし、スクリプトの先頭で globals() を呼び出すと、関数がまだ定義されていないため関数が含まれないため、これを行うことはできません。

おそらく、単純に洗練されていないソリューションに落ち着くべきか、慣用的な方法でスクリプトを書いていないのかもしれません。いずれにせよ、ご意見やご提案をいただければ幸いです。

4

3 に答える 3

8

あなたはデコレータについて間違っています。それらは関数が定義されるときに一度呼び出され、それらが返す関数は関数名に割り当てられた値であり、毎回呼び出されるのはその関数です。ランタイム オーバーヘッドを発生させることなく、デコレータで必要なことを行うことができます。

my_functions = []

def put_in_list(fn):
    my_functions.append(fn)
    return fn

@put_in_list
def function1():
    pass

@put_in_list
def function2():
    pass

PS: いずれにせよ、実行時のオーバーヘッドについて心配する必要はおそらくないでしょう。

PPS: また、奇妙なことを最適化しようとしています。ファイル内のリストを維持するだけの方がよい場合があります。どのくらいの頻度で関数を追加していますか? ソース ファイルでリストを更新するのは難しくありません。

于 2012-06-22T21:23:55.370 に答える
1

関数呼び出しにオーバーヘッドを追加しないデコレーターの使用例:

my_list = []

def add_to_my_list(func):
    print 'decorator called'
    my_list.append(func)
    return func

@add_to_my_list
def foo():
    print 'foo called'

@add_to_my_list
def bar():
    print 'foo called'

print '-- done defining functions --'
my_list[0]()
my_list[1]()
于 2012-06-22T21:29:24.070 に答える
0

この問題を解決する 1 つの方法は、これらすべての関数を 1 つのコンテナーに入れ、コンテナーから関数を抽出してリストを作成することです。

最も Pythonic なコンテナはclass. クラスのメンバー関数にするように言っているわけではありません。クラスでそれらを定義するだけです。

class MyFunctions(object):
    def func0():
        pass
    def func1():
        pass

lst_funcs = [x for x in MyFunctions.__dict__ if not x.startswith('_')]

しかし、私はデコレーターのアプローチの方がさらに好きです。それはおそらく最も Pythonic なソリューションです。

于 2012-06-22T21:28:38.067 に答える