2016-04-16 46 views
2

以下のコードを考慮してください。Pythonのパラメータは実際に引数の別名ですか?

a = [] 

def func1(x): 
    return x 

for i in range(3): 
    def func2(): 
     return func1(i) 

    a.append(func2) 

for k in range(3): 
    print(a[k]()) 

これは

http://gestaltrevision.be/wiki/python/aliases(最後のセクション)の 'エイリアスの使用' から

プリントアウトするとhttp://gestaltrevision.be/wiki/python/functions_basicsの '適用範囲' セクションでは、私がいることを学びました関数の引数は実際に渡される引数のエイリアスです。

xがiはループが実行されるたびに再割り当てされていても、私のエイリアスとして格納されるので

def func1(x): return x 

for i in range(3): 
    def func2(): return func1(i) 

に私は推論だからによれば、それはそのエイリアスには関係しないであろう、バツ。

だから私は、最初の3つの出力0、1、2のラインの代わりに、2、2、2

を期待あなたは私がここで間違って何をしたか説明できますか?ありがとう

答えて

2

あなたのコードは、あなたが望むように仕事をしたい場合は、今すぐ

def func2(i): 
    def func1(): 
     return i 
    return func1 

a = [func2(i) for i in range(3)] 
for k in range(3): 
    print(a[k]()) # prints 0 1 2 

を次のように行う、なぜあなたのコードの作業はしませんでしたか?オブジェクトがクロージャー内の名前にバインドされているときは、それは、func1です。あなたのコードでは、実行時にパラメータxからfunc1がバインドされています。したがって、aの各関数がfunc1(i)で、印刷時の値がiの場合は2です。したがって、コンパイル時にfunc2func1、がすでにfunc1にバインドされているときにバインドすることが解決策です。

+0

Oooh。つまり、実行時にxにバインドされるオブジェクト(別の名前として、もちろん)と関係がありますか? (私は値を印刷する?) –

+0

@NamanJainあなたのコードでは、 'func1'の本体は実行時まで' i'について知りません。 **遅れ評価**のためです。だから、最後の瞬間に '関数func1(I)' iの範囲でfunc1'が、それは2 –

+0

ある 'i'のために見つけたどのような値使用しますが、何のために」について'を評価する場合(3): デフ関数func2(K = i): return func1(k) '?私はこれを試しましたが、これは0 1 2を印刷しました。 –

2

ここで、囲みスコープから変数iを使用するclosure func2を作成します。 func2のインスタンスは、FORループ実行時にDEF文によって作成されます。

次に、FORループが終了した後にfunc2を実行します。 Pythonではループの終了後にループ変数が破棄されません。 したがって、クロージャは、ループを終了する瞬間に、囲みスコープでiの現在の値を使用します。

このコードでは、func1は何も変更しません。その結果は、それがなければ同じ結果になります。

+0

質問は可能です。http://stackoverflow.com/questions/233673/lexical-closures-in-python –

0

あなたが行う場合は、この:あなたは[0, 1, 2]内のすべてのiのためにあなたのfunc2を "再定義" している

for i in range(3): 
    def func2(): 
     return func1(i) 

。生きる最後の定義は:

def func2(): 
    return func1(2) 

これは簡単です。残念ながら、それはあなたが期待するように動作しません。

関連する問題