在wxPython中,如何绑定到循环中的独立对象,包括参数?

在wxPython中,如何绑定到循环中的独立对象,包括参数?,python,wxpython,Python,Wxpython,我不确定我是否正确地表达了这个问题,代码可能会更清晰 我在WxPython应用程序中添加了一个非常简单的插件系统,插件选项被简单地添加到一个子菜单中,一旦单击它们,插件的操作就会执行。我是wx的新手,所以可能有一些简单的事情我做错了,所以我很乐意被告知 以下代码按预期工作,并调用单击菜单选项的插件“performAction”方法 for plugin in self.pluginManager.plugins: wxId = wx.NewId() plugin_submenu.

我不确定我是否正确地表达了这个问题,代码可能会更清晰

我在WxPython应用程序中添加了一个非常简单的插件系统,插件选项被简单地添加到一个子菜单中,一旦单击它们,插件的操作就会执行。我是wx的新手,所以可能有一些简单的事情我做错了,所以我很乐意被告知

以下代码按预期工作,并调用单击菜单选项的插件“performAction”方法

for plugin in self.pluginManager.plugins:
    wxId = wx.NewId()
    plugin_submenu.Append(wxID,plugin.displayName)
    canvas.Bind(wx.EVT_MENU, plugin.performAction)
我还想为插件操作添加参数,这导致我使用lambdas,因为“bind”方法的第二个参数应该是可调用的。这似乎是一个相当不起眼的变化:

for plugin in self.pluginManager.plugins:
    wxId = wx.NewId()
    plugin_submenu.Append(wxID,plugin.displayName)
    canvas.Bind(wx.EVT_MENU, lambda evt, temp=objArgs: plugin.performAction(evt,temp)
如所述。然而,当我这样做时,无论最后绑定哪个插件对象,都会被调用,而不管实际单击了哪个菜单选项。我真的不知道为什么行为会从第一个代码示例变为第二个,但确实如此,我被难住了


那么,有人知道为什么会发生这种情况吗?我该怎么做才能得到我所期望的行为

您的问题是python的作用域规则。在第一种情况下,在执行此代码时,您已将
插件的特定实例绑定到画布

在第二种情况下,在执行此代码时,您已经将一个特定函数(lambda函数)绑定到画布上。不幸的是,lambda函数引用了一个插件对象,在事件发生之前,该对象实际上不会得到计算。当您的事件发生时,这段代码将很长时间执行完毕,您将触发的实际
插件将是最后一个遇到的插件

“捕获”实际插件实例的一种方法是在lambda定义中捕获它,将其作为额外参数传入:

for plugin in self.pluginManager.plugins:
    wxId = wx.NewId()
    plugin_submenu.Append(wxID,plugin.displayName)
    canvas.Bind(wx.EVT_MENU, lambda evt, p=plugin, temp=objArgs:    
                p.performAction(evt,temp))

我不确定我是否给出了一个很好的解释,说明了为什么/如何发生这种情况,但这是另一个可能会有所帮助的解释。

因此,首先,我正在通过插件对象进行循环,一切都很正常。在第二个例子中,lambda在事件激发之前不会被计算?正确。每次迭代都会创建一个新的lambda函数,但每个lambda函数最终都会引用相同的
插件。通过将
plugin
分配给其中一个lambda参数,我的示例“捕获”了正确的
plugin
,作为lambda函数instance.Ugh的一部分。我可能永远也不会意识到这是在我自己身上发生的,我假设问题是wx的绑定函数。不过,现在我知道了,情况还不错。谢谢你的帮助。