1

我目前正在尝试创建一个循环,将事件-动作对绑定在一个字典中。回调函数只是调用动作函数并打印参数。

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>

也就是说,逃逸和返回事件似乎都绑定了toggleChat...

我对 lambda 表达式几乎没有经验,但我希望为每个循环创建一个新的无名函数。我错了吗?如果没有,问题可能出在哪里?

提前感谢您的见解。

4

2 回答 2

3

为 lambdas 创建闭包的习惯用法是通过默认参数传递您希望绑定的对象

self.top.bind(binding, lambda event, action=action: self.callback(event, self.actionRep.__class__.__dict__[action]))
于 2013-05-20T16:05:54.263 回答
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
于 2013-05-20T16:06:14.250 回答