2010-08-07 81 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声明。