3

2 つのスクリプトがあるとします。

test_fun1.py

a = 1

def test1():
    print a
    execfile('test_fun2.py')

test1()

test_fun2.py

b = 2    

def print_a():
    print 'a'

def test2():
    print_a()
    print b

test2()

実行するtest_fun1.pyと、次のエラーが表示されます。

NameError: global name 'print_a' is not defined

両方print_a()内外test2()してプリントされますaと。b変数はグローバルに設定されるのに、関数は設定されないのはなぜですか?

4

1 に答える 1

1

これはかなり興味深い問題です。最初の簡単な回避策として、 を呼び出すときにローカルおよびグローバル名前空間として使用する辞書を指定できますexecfile()。空の辞書を使用すると正常にglobals動作します。

# test_fun1.py
a = 1

def test1():
    print a
    execfile('test_fun2.py', {})

test1()

または、モジュールのグローバル スコープ内でコードを実行する場合は、globals()代わりに{}.

これが機能しない理由について説明します...のドキュメントからexecfile()

両方の辞書を省略した場合、式はexecfile()が呼び出された環境で実行されます。

ここで「両方の辞書」は、オプションのglobalsおよびlocals引数を参照していますexecfile()。この場合、「呼び出される環境」は、 test_fun1.pyexecfile()内の関数のローカル スコープです。test1()これが機能することを期待するのは合理的です。これは、次と本質的に同等のことを行う必要があるように思われるためです。

a = 1

def test1():
    print a
    # code executed by execfile
    b = 2    

    def print_a():
        print 'a'

    def test2():
        print_a()
        print b

    test2()

test1()

ただし、ドキュメントの後半にメモがあります。

注:デフォルトローカルは、以下の機能で説明されているように機能locals()します。デフォルト ローカル ディクショナリへの変更は試行しないでください。関数が戻った後にコードがローカルに与える影響を確認する必要がある場合は、明示的なローカル ディクショナリを渡します。関数のローカルを変更するために確実に使用することはできません。execfile()execfile()

これで、関数のローカルを確実に変更するために使用できない明示的な警告がここにexecfile()あり、それがまさにこのコードが行おうとしていることです。b = 2andステートメントはのdef print_a(): ...スコープ内で実行されますが、test1()これらの名前を名前空間に追加することに実際には成功していないため、後でそれらの名前にアクセスしようとすると失敗します。

于 2013-08-13T19:06:39.440 に答える