2017-06-09 11 views
3

私はプログラミングに慣れておらず、スキムは機能やクラスに関するいくつかのトピックを読んでいます。 関数と関数を囲んでいることを読んだあと、関数とそのスコープを集めるだけで、クラスの継承検索を模倣しようとしました。囲み関数スコープ検索?

例:コード

def f1(): 
    t=1 
    def f2(x): 
     return eval(x) 
    return f2 

については

f1()('t') #expecting 1 return

でもないと言う

def f1(): 
    t=1 
    def f2(): 
     return t 
    return f2 
を定義行っているとき、私は名前のエラーが出るのはなぜ

f()() # 1 is returned here

この問題は、tをf2のスコープ内で非ローカルとして定義することで解決できます。これは、最初のコードがf2のローカルスコープでしかないことを意味します。なぜこれが起こるのですか? `

+2

コードをインデントしてください。 – ForceBru

+0

[関連](https://stackoverflow.com/questions/44425363/is-it-true-in-python-closure-will-be-stored-if-and-only-if -it-is-mention-lex) –

+0

https://stackoverflow.com/questions/4020419/whyarent-python-nested-functions-called-closuresの受け入れられた答えを見てください - 非常に良い説明があります。 – mkiever

答えて

1

ここでの問題はのコンテキストです。デフォルトでは、evalは呼び出された環境のローカルとグローバルを使用します。私たちが書く場合:

def f1(): 
    t = 1 

    def f2(x): 
     return eval(x) 
    return f2 

を、その後f2内、tは、グローバルまたは地元の人々のいずれかに含まれていないので、evalのステートメントにアクセスできなくなります。実際にf2の中でtが実際に使用される場合、Pythonはtf2のローカルに追加します。このように、やや驚くべきことには、次のコード正しく実行されます:

def f1(): 
    t = 1 

    def f2(x): 
     print(t) 
     return eval(x) 
    return f2 

tが今f2内で使用しているため。これは常に働く確保のより良い方法は、次の操作を行うことです。

def f1(): 
    t = 1 
    eval_globals = globals() 
    eval_locals = locals() 

    def f2(x): 
     return eval(x, eval_globals, eval_locals) 
    return f2 

これはf1の範囲内からグローバルや地元の人々を提供し、evalのためのコンテキストを上書きします。

あなたは新しいプログラマだと言われているので注意してください。一般的に、あなたが正当な理由がない限り、評価期間を避けるべきです。あなたがここでやっていることを評価に頼らずに達成するより良い方法があります。