2013-06-26 33 views
1

我已經偶然發現了一些傷害了我的大腦的東西。考慮以下python value versus reference

fs = [] 
for i in range(3): 
    fs.append(lambda : normal(i, .001)) 
    print mean([fs[-1]() for j in range(1000)]) 
print [mean([fs[i]() for j in range(1000)]) for i in range(3)] 

返回,例如,

-1.38651717873e-05                             | 
1.00003545604                               | 
1.99999343229                               | 
[2.0530899455777235e-05, 0.99995283932453838, 2.0000045292311737] 

如預期。現在修改的事情略有

fs = [] 
for i in range(3): 
    mu = i 
    fs.append(lambda : normal(mu, .001)) 
    print mean([fs[-1]() for j in range(1000)]) 
print [mean([fs[i]() for j in range(1000)]) for i in range(3)] 

,我們得到

5.56620751611e-06                              | 
0.999999076252                              | 
1.99995161119                               | 
[2.0000016397219098, 1.9999853403014964, 2.0000209870831158] 

即各2個,循環外的人的。在對我的大腦進行kerploding後,我記得python中的引用/範圍是邪惡的,看起來答案是,通過正常的mu被存儲在引用中,而不是按值存儲(儘管mu應該用正常語言進行範圍映射) 。那是怎麼回事?我如何在未來的編碼中避免類似的瘋狂?

+1

相關:HTTP:/ /stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture-in-python –

回答

1

Python中的封閉是按名稱(好吧,不是技術上的,但你可以這樣想)。因此,對於mu,每個lambda的值都是2,因爲這是在循環中給予mu的最後一個值。要修復的mu在函數定義時間的價值,只使用默認參數值,像這樣:

lambda mu=mu: normal(mu, .001) 

(作用域規則真的沒有任何與此。)

+0

是的工作。你能指引我到哪裏讀「封鎖」嗎?我不熟悉術語 – andyInCambridge

+0

http://www.shutupandship.com/2012/01/python-closures-explained.html – Elazar

+0

http://en.wikipedia.org/wiki/Closure_(computer_science) – Elazar