20

私の疑惑は、私がやりたいことは、Pythonではきれいに実行できないということです。相互に呼び出すネストされた関数をいくつか示します。(一般に、それらは字句スコープである必要はありませんが、動的に相互に呼び出す必要があります。)

def outer() :
    s_outer = "outer\n"

    def inner() :
        s_inner = "inner\n"
        do_something()

    inner()

ここで、呼び出すときにdo_something()、呼び出し元の関数の変数にアクセスしたいと思います。この場合は、呼び出しスタックのさらに上にs_outerありs_innerます。

残念ながら、ここでのキーワードは、関数内でnonlocal定義した場合にのみ役立ちます。ただし、同じレベルで定義すると、キーワードは機能しません。do_something()inner()outer()nonlocal

ただし、他のさまざまな関数から呼び出したいのですdo_something()が、常にそれぞれのコンテキストで実行し、それぞれのスコープにアクセスします。

いたずらを感じて、私は次のように内部から呼び出すことができる小さなアクセサを書きましたdo_something()

def reach(name) :
    for f in inspect.stack() :
        if name in f[0].f_locals : return f[0].f_locals[name]
    return None 

その後

def do_something() :
    print( reach("s_outer"), reach("s_inner") )

うまく動作します。

私の2つの質問はこれらです

  1. この問題を解決するためのより良い方法はありますか?(それぞれのデータをdictにラップし、これらのdictを明示的にに渡す以外do_something()

  2. reach()関数を実装するためのよりエレガントで短縮された方法はありますか?

乾杯!

4

3 に答える 3

7

reach理解、デバッグ、テスト、および保守が非常に難しい新しい非標準の間接参照を導入するため、実装のエレガントな方法はありません。Pythonのマントラ(try import this)が言うように:

明示的は暗黙的よりも優れています。

したがって、引数を渡すだけです。未来からのあなたは、今日からあなたに本当に感謝するでしょう。

于 2013-03-25T06:40:54.753 に答える
7

私がやったのは

scope = locals()

からscopeアクセスできるようにしdo_somethingます。そうすれば、到達する必要はありませんが、呼び出し元のローカル変数のディクショナリにアクセスできます。これは、自分で辞書を作成して渡すのとよく似ています。

于 2013-04-06T07:27:21.663 に答える
3

この問題を解決するためのより良い方法はありますか?(それぞれのデータをdictにラップし、これらのdictを明示的にdo_something()に渡す以外)

dictを明示的に渡すのがより良い方法です。

あなたが提案していることは非常に型破りに聞こえます。コードのサイズが大きくなると、モジュール間にクリーンなAPIを使用して、コードをモジュラーアーキテクチャに分割する必要があります。また、理解しやすく、説明しやすく、他のプログラマーに渡して変更/改善/デバッグしやすいものでなければなりません。あなたが提案しているのは、データフローが自明ではない、型にはまらないクリーンなAPIではないように思えます。彼らがそれを見たとき、それはおそらく多くのプログラマーを不機嫌にするだろうと私は思う。:)

もう1つのオプションは、関数をクラスのメンバーにし、データをクラスインスタンスに含めることです。問題がデータオブジェクトを操作するいくつかの関数としてモデル化できる場合、これはうまく機能する可能性があります。

于 2013-04-07T22:00:52.883 に答える