2012-12-11 38 views
1

可能重複:
What do (lambda) function closures capture in Python?奇怪的行爲在通過列表理解定義的多種功能

有了這個代碼:

def problem(): 
    PHI_LIST_0 = [lambda a, b: a+b+u for u in xrange(3)] 
    PHI_LIST_1 = [lambda a, b: a+b+0, lambda a, b: a+b+1, lambda a, b: a+b+2] 

    for phi in PHI_LIST_0: print "v0:", phi(1,1) 
    print 
    for phi in PHI_LIST_1: print "v1:", phi(1,1) 

if __name__ == '__main__': 
    problem() 

我得到:

v0: 4 
v0: 4 
v0: 4 

v1: 2 
v1: 3 
v1: 4 

預期的行爲是最後一個,PHI_LIST_1。我想我理解爲什麼結果與PHI_LIST_0不同:也許是因爲Python在評估phi(1,1)時使用了最後一個'u',即2。

但是我想用一個列表理解來定義PHI_LIST_0定義的函數列表。有人知道我能做到嗎?

回答

2

當你定義一個函數時,它會在函數體內的自由變量上創建一個閉包。在您的PHI_LIST_0中,這是變量u。它不保留你的價值,它保持對你的名字的引用。當你調用函數時,它使用u的當前值。因此,所有的函數都引用相同的變量,並且所有的函數都看到相同的(最後一個)值,所以它們都表現相同。

你可以使用默認值絕招解決這個問題:

PHI_LIST_0 = [lambda a, b, u=u: a+b+u for u in xrange(3)] 

現在定義的函數當U參數的缺省值的計算,並存儲與功能。

+0

這就是我的想法,但後來我使用'copy'來獲取'u'的值,但它仍然沒有按預期工作。 - 但你的解決方案是優雅的,它很好地工作。 :) –

+0

非常感謝!它完美的作品。 –