2010-08-07 78 views
39

我試圖在循環中創建函數並將它們存儲在字典中。 問題是,字典中的所有條目似乎都會映射到最後創建的函數。該代碼是這樣的:在循環中創建函數

d = {} 
def test(**kwargs): 
    for k in kwargs: 
     def f(): 
      print k, kwargs[k] 
     d[k] = f 
     f() 

test(foo=1, bar=2) 
print 'should print the same output as before' 
d['foo']() 
d['bar']() 

此輸出:

foo 1 
bar 2 
should print the same output as before 
bar 2 
bar 2 

任何想法,爲什麼?

+1

作爲提醒我自己:http://docs.python-guide.org/en/latest/writing/gotchas/#late-binding-closures – 2014-09-10 17:20:52

回答

82

您正在運行到一個問題後期綁定 - 每個功能查找k儘可能晚的(因此,當叫外面test,這個循環結束後發生)。

迫使早期綁定容易解決:改變def f():def f(k=k): - 默認值(在k=k右手k是參數名k,這是左側kk=k默認值)的擡頭def時間,而不是在call時間,所以基本上他們是專門尋找早期綁定的一種方法。

如果你擔心f獲得一個額外的參數(因此可能被錯誤地稱呼),還有一個更復雜的方式使用閉包作爲「功能工廠」其中涉及:

def make_f(kwargs, k): 
    def f(): 
     print k, kwargs[k] 
    return f 

,並在您的循環使用f = make_f(kwargs, k)而不是def聲明。