2017-09-14 6 views
7

:私は、例えば、他の文字にIを変更場合、出力は異なる変数名が異なる結果をもたらすのはなぜですか(python2.7)?このコードで

"0x107dea668で機能内側"

results = [] 
for i in [1, 2, 3, 4]: 
    def inner(y): 
     return i 
    results.append(inner) 

for i in results: 
    print i(None) 

ある

results = [] 
for i in [1, 2, 3, 4]: 
    def inner(y): 
     return i 
    results.append(inner) 

for j in results: 
    print j(None) 

出力が「4」


回答

results = [] 
for i in [1, 2, 3, 4]: 
    def inner(y): 
     print "in inner:%s " % id(i) 
     return i 
    results.append(inner) 

# i -> 4 
for i in results: 
    # i -> func inner 
    print "i: %s" % i 
    print "in loop: %s " % id(i) 

    # func inner <===> A 
    # i == A -> return i -> return A, so when call funtion inner, will return itself 
    # print "call: %s" % i(None) 

    print "call: %s" % i(None)(None)(None) 
    print "------------------------------" 

I:4315172208
コール:内側における4315172208
:内側における4315172208
:4315172208
内側のループで0x101344d70
の内関数:機能インナー0x101344d70

I:内部における4315172328
:4315172328
内で:内側における4315172328
:ループ内0x101344de8
の内機能4315172328
コール:0x101344e60の内関数:内部機能0x101344de8

iにおけるインナーで4315172448
:4315172448
内で:内側における4315172448
ループ内
コール:インナー機能0x101344e60

でI:0x101344ed8

で機能内側:内側における4315172568
:4315172568
内で:内側における4315172568
:4315172568
呼び出しループ内0x101344ed8
の内機能
+3

あなただけの関連i' –

+0

'の遅延評価を満たし:https://stackoverflow.com/questions/42805800/generator-comprehension-different-output-from-list-comprehension –

+0

これは関係ありません怠惰な評価には、文脈の問題です。遅延評価とは、必要なときだけ評価することであり、必要なときは評価しません。 –

答えて

1

可変i 4に返さ印刷:

時々Pythonで使用されるほとんどトリック値を含有する細胞として変数のデフォルト値を使用することですinner関数は、割り当てられた最後のコンテキストからその値を保持します。

inner関数内のブレークポイントを使用してコードをデバッグすると、関数を呼び出す前に前のフレーム/コンテキスト(図の左下)を選択すると画像がより明確になります。

iを使用すると、2番目のforの内部に割り当てられますので、その値として機能します(図1の黄色で強調表示)。リストの上にfor(図2):あなたがjを使用する場合

Figure 1

さて、変数iは前の文脈からその最後の値を保持します。

Figure 2

1

実際には、結果でjを使用すると、変数iは最初のループの後にあるため、変数iは4のままです。

しかし、結果でiを使用すると、結果の中に格納されている関数を参照します。あなたがそれを呼び出すまで、私は固定されていません。 @ジャンフランソワファーブルが言ったように、怠惰な評価。

さらに、あなたは1-4のループは、あなたが部分関数を使用し、関連範囲 Iに格納する必要がある場合、各Iを格納するために内部関数をしたい場合。

from functools import partial 

results = [] 
for i in [1, 2, 3, 4]: 
    def inner(i, y): 
     return i 


    results.append(partial(inner, i)) 

for i in results: 
    print(i(None)) 

これはあなたにもっと意味がある

1 
2 
3 
4 

の結果が得られます。あなたが定義した

3

inner機能は、グローバル変数iを参照自由変数が含まれています。

def inner(y): 
    return i 

i = 1 
print inner(None) 

i = 2 
print inner(None) 
innerへの呼び出し時に、1あなたの最初の例では、次に2

を印刷

i関数である値を有し、これはこのような例では、おそらく明確ですだからi(これはinner)と呼ばれるものが印刷されます。第2の例で

は、innerへの呼び出し時に、iは値4を有しており、その結果は、(innerある)jが呼び出されたときに印刷されているものです。別のanswerで推奨されているように

あなたはおそらくここに望んで表現する明確な方法は、部分的に評価された関数を使用することです。別の方法は、クロージャを作成するために囲み関数を使用することです。このように:

results = [] 
for i in [1, 2, 3, 4]: 
    def outer(k): 
     def inner(y): 
      return k 
     return inner 
    results.append(outer(i)) 

for i in results: 
    print i(None) 

これはおそらく1から4を出力します。

results = [] 
for i in [1, 2, 3, 4]: 
    def inner(y, i = i): 
     return i 
    results.append(inner) 

for i in results: 
    print i(None) 

も1

関連する問題