1

関数として呼び出したいユーティリティをいくつか書いています。それらは、変化しない傾向があるコンテキストといくつかのデータで呼び出されます。コンテキストを使ってフッキングを行うには多くの時間がかかりますが、それが完了すると、それを使用してデータをむき出しにすることはかなり軽量です。

これは明らかに次のパターンにうまくマッピングされます

class MyFunc():
    def __init__(self, context):
        self.foo_d_context=foo(context)
    def __call__(self, data):
        return bar(self.foo_d_context, data)

if __name__ == '__main__':
    my_callable=MyFunc(my_context)

    results1=my_callable(my_data1)
    results2=my_callable(my_data2)

しかし、私のユーザーは my_callable オブジェクトの最初の作成に反対しています。彼らにとってより受け入れられるのは、次のように使用できる機能です...

results=my_func(my_context, my_data)

...そして関数 my_func に、前の呼び出しからの既存のデータが存在するかどうかを確認させ、最後の呼び出しと同じです。

これに関する問題は、関数が初めて呼び出されたときです。永続データをどこに保存できますか? すでに Python 標準ライブラリに含まれているいくつかのユーティリティは、このように機能すると述べているようで、ドキュメントでは、オブジェクトをセットアップするヘルパー関数について説明しています。しかし、私はそれがどのように機能するかを理解していません。

私はそれを行う方法を考えることができますが、それは間違っていると感じます。オブジェクトを globals() 名前空間に直接配置でき、任意の関数内から実行できるようです。だから私はできる

def my_func(context,data):
    glob=globals()
    try:
        if glob['__my_persistent_reference_context_$$$'] == context:
            return bar(glob['__my_foo_d_context_$$$'],data)
    except KeyError:
        pass
    glob['__my_foo_d_context_$$$']=foo(context)
    glob['__my_persistent_reference_context_$$$'] = context
    return bar(glob['__my_foo_d_context_$$$'],data)

上記を書いた後、この関数は MyFunc クラスのオブジェクトを作成できることに気がつきました。これは、私が探している概念に近いように聞こえますが、それでも何かを呼び出してどこかに配置する必要があるため、そうではありません。 「グローバル名前空間を使用できますか?」という基本的な問題を解決できません。問題。

これでよろしいですか?

それは常に機能しますか?(私は 2.6.6 を使用していますが、最終的には 3 でも動作しますか?)

それを行うより良い方法はありますか?

汚染するより良い名前空間はありますか?

クラスの方法が単に正しい方法であると主張する必要がありますか?

4

2 に答える 2

2

あなたが言っていることから、あなたがしたいのは値をキャッシュすることだと思います。これは、他の名前空間に影響を与えない関数属性を使用することで、非常に簡単に実行できます。

def my_func(context, data):
    try:
        reference, saved = my_func.cache
    except AttributeError:
        reference, saved = None, None
    computed = saved if reference == context else foo(context)
    my_func.cache = context, computed
    return bar(computed, data)
于 2013-01-09T16:37:13.037 に答える
0

確かに何でも入れることができglobals()、識別子として無効にする文字をキーに使用すると、「通常の」方法ではアクセスできなくなります。しかし、これを一歩一歩進めていきましょう。辞書を使うなら、自分の辞書を使ってみませんか? それを使用する関数でグローバルに宣言する必要さえありません。

_my_global_state = {}

def foo(x):
    _my_global_state.setdefault("counter", 0)
    _my_global_state["counter"] += x

等々。

しかし、属性構文の方が優れているので、オブジェクト インスタンスを使用しましょう。

_my_global_state = object()

def foo(x):
    if hasattr(_my_global_state, "counter"):
        _my_global_state.counter += x
    else:
        _my_global_state.counter = x

もちろん、その飛躍を遂げた今、データと関数を 1 つのものにまとめることもできます。これが本当の解決策です。クラスを使用して、データとそれを操作する関数を保持します。

于 2013-01-09T16:31:25.807 に答える