15

これは期待どおりに機能します

def outer_func():
    from time import *

    print time()

outer_func()

コンテキスト内でネストされた関数を細かく定義し、他のネストされた関数から呼び出すことができます。

def outer_func():
    def time():
        return '123456'

    def inner_func():
        print time()

    inner_func()

outer_func()

個々の関数をインポートすることもできます。

def outer_func():
    from time import time

    def inner_func():
        print time()

    inner_func()

outer_func()

ただし、これは次のようにスローしSyntaxError: import * is not allowed in function 'outer_func' because it contains a nested function with free variablesます。

def outer_func():
    from time import *

    def inner_func():
        print time()

    inner_func()

outer_func()

これがベストプラクティスではないことは承知していますが、なぜ機能しないのですか?

4

1 に答える 1

22

コンパイラには、タイムモジュールが。という名前のオブジェクトをエクスポートするかどうかを知る方法がありませんtime

ネストされた関数の自由変数は、コンパイル時にクロージャーセルに関連付けられます。クロージャーセル自体は、まったく関連付けられていないグローバルとは対照的に、コンパイルされたコードで定義された(ローカル)変数を指します。Pythonデータモデルを参照してください; func_globals関数は属性を介してグローバルを参照し、func_closure属性は一連のクロージャーセル(またはNone)を保持します。

そのため、ネストされたスコープで動的インポートステートメントを使用することはできません。

そして、なぜ入れ子関数はクロージャーセルを必要とするのですか?関数自体が終了したときにローカル関数変数を参照するメカニズムが必要なため、次のようになります。

def foo(spam):
    def bar():
        return spam
    return bar

afunc = foo('eggs')

を呼び出すことによりfoo()、スコープ変数を参照するネストされた関数を取得しました。コンパイラは、そのスコープ変数を再度取得できるように、インタプリタに必要な参照を作成する必要があります。したがって、セル、およびそれらに課せられた制限。

于 2012-11-19T15:11:53.627 に答える