2

Python のドキュメントには、「関数のローカルを変更するために execfile() を確実に使用することはできません」と記載されています。ページhttp://docs.python.org/2/library/functions.html#execfile

誰かがこの声明についてさらに詳細を提供できますか? ドキュメントはかなり最小限です。この文は、「両方の辞書を省略した場合、式は execfile() が呼び出された環境で実行される」と非常に矛盾しているように見えます。これはドキュメントにもあります。関数内で excecfile が使用され、新しいスコープ レベルを作成するという点で、execfile が関数と同じように動作する特殊なケースはありますか?

次のような関数で execfile を使用する場合

def testfun():
    execfile('thefile.py',globals())
    def testfun2():
        print a

また、'thefile.py' のコマンドによって作成されたオブジェクト (オブジェクト 'a' など) があります。それらが testfun のローカル オブジェクトになるか、グローバル オブジェクトになるかはどうすればわかりますか? では、関数 testfun2 では、「a」はグローバルに見えるでしょうか? execfile ステートメントから globals() を省略した場合、'thefile.py' 内のコマンドによって作成されたオブジェクトが 'testfun' で使用できない理由を、より詳細に説明できる人はいますか?

4

2 に答える 2

1

ローカルは、Python ではちょっと変わっています。通常のローカル変数は通常、バイトコード内の名前ではなくインデックスによってアクセスされますが (これは高速であるため)、これは Python がコンパイル時にすべてのローカル変数を認識している必要があることを意味します。つまり、実行時に新しいものを追加することはできません。

現在、execPython 2.x の関数で を使用する場合、Python はこれを実行しないことを認識しており、名前でローカル変数にアクセスする低速の方法にフォールバックし、プログラムで新しい変数を作成できます。(このトリックは Python 3 で削除されました。) Python も に対してこれを行うと思われるかもしれませんが、そうexecfile()execexecfile()ありません。execfileランタイム (結局のところ、再割り当てできます)。

サンプル関数では何が起こるでしょうか? さて、それを試してみてください!状態のドキュメントとしてexecfile、ローカル dict を渡さない場合は、グローバルとして渡した dict が使用されます。globals()(モジュールの実際のグローバル変数)を渡すので、に割り当てられると、グローバルaaなります。

今、あなたは次のようなことを試すかもしれません:

def testfun():
    execfile('thefile.py')
    def testfun2():
        print a
    return testfun2
    exec ""

最後のexecステートメントはtestfun()、古いスタイルの名前ベースのローカル変数を使用することを強制します。ここにないので、実行する必要さえありません。関数のどこかにある必要があります。

ただし、名前ベースのローカルは自由変数を使用したネスト関数をサポートしていないため (aこの場合)、これも機能しません。この機能では、Python が関数定義時にすべてのローカル変数を認識している必要もあります。上記の関数を定義することさえできません — Python ではできません。

要するに、プログラムでローカル変数を処理しようとするのは苦痛であり、ドキュメントは正しいです:execfile()関数のローカル変数を変更するために確実に使用することはできません.

おそらく、より良い解決策はimport、ファイルをモジュールとしてだけにすることです。関数内でこれを行うと、通常の方法でモジュール内の値にアクセスできます。

def testfun():
    import thefile
    print thefile.a

実行時までインポートするファイルの名前がわからない場合は、__import__代わりに使用できます。また、インポート元のディレクトリがパスの最初にあることを確認するために変更する必要がある場合がありsys.pathます (おそらく後で元に戻します)。

また、独自の辞書を渡したりexecfile、後で実行したファイルから変数にアクセスしたりすることもできますmyVarsDict['a']

于 2013-04-17T16:52:38.477 に答える