我目前正在尝试创建一个循环来绑定dict中的事件动作对。 回调函数只调用action函数并打印参数。
for binding, action in self.keyMap.revMap.items() :
print binding, action
self.top.bind(binding,
lambda event : self.callback(event, self.actionRep.__class__.__dict__[action]))
print self.top.bind()
在绑定时,我得到这些日志:
<Escape> toggleMenu -------------generated by the line "print binding, action"
<Return> toggleChat -------------generated by the line "print binding, action"
('<Key-Return>', '<Key-Escape>', '<Key>') ---generated by the line "print self.top.bind()"
事件 - 行动夫妇是正确的。 但是,当事件发生时,我有这个:
<Tkinter.Event instance at 0x0000000002BB3988> <function toggleChat at 0x0000000002B60AC8>
<Tkinter.Event instance at 0x0000000002BB3948> <function toggleChat at 0x0000000002B60AC8>
也就是说,escape和return事件似乎都绑定到toggleChat ...
我对lambda表达式的经验不多,但我希望为每个循环创建一个新的无名函数。我错了吗?如果没有,问题出在哪里?
提前感谢您的见解。
答案 0 :(得分:3)
为lambdas创建闭包的习惯用法是通过默认参数传递你想要绑定的对象
self.top.bind(binding, lambda event, action=action: self.callback(event, self.actionRep.__class__.__dict__[action]))
答案 1 :(得分:2)
让我们先看一下常规函数的行为:
x = 2
def foo():
return x
x = 3
print foo() #3
现在我们看到当一个函数从封闭命名空间中获取一个变量时,它会返回该变量的当前值,而不是定义该函数时的值。但是,我们可以通过创建默认参数来强制它获取值,因为它们是在函数创建时计算的,而不是在函数创建时计算的。
x = 2
def foo(x=x):
return x
x = 3
print foo() #2
lambda
功能没有任何不同。在循环中创建了新的无名函数,但是当你真正去评估函数时,你会在循环终止时获取循环变量的值。为了解决这个问题,我们只需要在创建函数时指定值:
funcs = [lambda i=i: i for i in range(10)]
print funcs[3]() #3