【问题标题】:Automatic binding using lambdas inside a loop [duplicate]在循环内使用 lambda 自动绑定 [重复]
【发布时间】:2013-05-15 05:57:32
【问题描述】:

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

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 表达式几乎没有经验,但我希望为每个循环创建一个新的无名函数。我错了吗?如果不是,问题可能出在哪里?

提前感谢您的见解。

【问题讨论】:

    标签: python tkinter


    【解决方案1】:

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

    self.top.bind(binding, lambda event, action=action: self.callback(event, self.actionRep.__class__.__dict__[action]))
    

    【讨论】:

      【解决方案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
      

      【讨论】:

      • 感谢您的深刻见解 :)。
      • @aPythonJourney -- 当然。我认为这是几乎每个人在他们的 python 之旅中都会遇到的事情之一。
      猜你喜欢
      • 2021-10-13
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      相关资源
      最近更新 更多