2013-05-26 70 views
2

的函數列表我有功能的陣列,例如:lambda函數和在Python

>>> def f(): 
...  print "f" 
... 
>>> def g(): 
...  print "g" 
... 
>>> c=[f,g] 

然後我嘗試創建兩個lambda函數:

>>> i=0 
>>> x=lambda: c[i]() 
>>> i+=1 
>>> y=lambda: c[i]() 

,然後打電話給他們:

>>> x() 
g 
>>> y() 
g 

爲什麼lambda中的c [i]是相同的?

+0

解決這個問題的_easy_方法是首先不創建無用的'lambda's。只需用'x = c [i]'和'y = c [i]'替換這兩行,就可以得到您想要的功能。編寫'lambda:f()'而不是'f'的唯一原因是將'f'粘貼到一個閉包名稱空間中以便稍後查看它,而不是僅僅使用它。你不想在這裏這樣做,事實上,這正是導致你的問題。 – abarnert

回答

10

這是因爲拉姆達函數獲取全局變量i在運行時的值:

>>> i = 0 
>>> x=lambda z = i : c[z]() #assign the current value of `i` to a local variable inside lambda 
>>> i+=1 
>>> y =lambda z = i : c[z]() 
>>> x() 
f 
>>> y() 
g 

必讀: What do (lambda) function closures capture?

+0

注意:鏈接問題的接受答案顯示如何進行所需的名稱捕獲(請參閱http://stackoverflow.com/a/2295368/25050結尾處的'createAdder'函數。 –

3

在Python關閉不捕獲實際值,而是他們捕獲命名空間。所以當你在你的函數中使用i時,它實際上是在封閉範圍內查找的。那裏的價值已經改變了。

您不需要所有那些lambda s和列表來查看此。

>>> x = 1 
>>> def f(): 
... print(x) 
... 
>>> x = 2 
>>> def g(): 
... print(x) 
... 
>>> g() 
2 
>>> f() 
2