2015-07-22 29 views
5

我想換一個函數指定的參數,像functools.partial,但預期它不工作:未能包裹函數拉姆達

source_codes = (0, 1, 2) 

def callback(source, *args): 
    print 'callback from source: ', source 

funcs = [] 
for source in source_codes: 
    funcs.append(lambda *args: callback(source, *args)) 

for i, func in enumerate(funcs): 
    print 'source expected: ', i 
    func() 
    print 

輸出:

source expected: 0 
callback from source: 2 

source expected: 1 
callback from source: 2 

source expected: 2 
callback from source: 2 

但...我想要的是:

source expected: 0 
callback from source: 0 

source expected: 1 
callback from source: 1 

source expected: 2 
callback from source: 2 

我知道它的作品,如果我使用functools.partial,但我想知道th在我的代碼中是真正的問題... lambda包裝是否使用全局變量source

回答

4

你的代碼中的問題是lambda表達式不會被計算,直到它被調用。

然後當它被調用時,它使用最新值source。它在創建lambda時不綁定source的值。

示例代碼顯示這種行爲 -

>>> y = lambda: z 
>>> z = 0 
>>> y() 
0 
>>> z = 1 
>>> y() 
1 
2

partial已經「凍結」了函數的參數和/或你傳給他的關鍵字,讓你可以簡單地消除lambda表達:

source_codes = (0, 1, 2) 

def callback(source, *args): 
    print 'callback from source: ', source 

funcs = [] 
for source in source_codes: 
    funcs.append(partial(callback, source)) 
    source = 30 # don't have any effects over partial function. 

for i, func in enumerate(funcs): 
    print 'source expected: ', i 
    func() 
    print