我正在使用python 3和tkinter,我遇到了一个我想从按钮执行命令的问题。生成可变数量的按钮,每个访问者一个,我试图从按钮按下调用函数signOut
,同时将相关项目(访问者)从列表传递给它。
我意识到问题出在for循环中,因为按下按钮时,i
将==
列表中的最后一项。如何使其具体针对实际访客。我似乎无法想到解决方案。任何建议都表示赞赏。
buttonDictionary = {}
for i in range(0,len(currentVisitors)):
buttonDictionary[i] = Button(bottomFrame, text=currentVisitors[i], command=lambda: signOut(topFrame, bottomFrame, currentVisitors[i]))
buttonDictionary[i].pack()
答案 0 :(得分:1)
我的理解是,例如这样的循环中的i
中的lambda
指的是变量i
本身,而不是每次迭代时变量的值,因此当command
回调时在调用时,它会使用当前i
的值,正如您所注意到的那样是最后一次迭代的值。
解决此问题的一种方法是使用partial
。 partial
实际上会冻结"循环中当前状态的参数,并在调用回调时使用它们。
尝试使用partial
代替lambda
,如下所示:
from functools import partial
buttonDictionary = {}
for i in range(0,len(currentVisitors)):
buttonDictionary[i] = Button(bottomFrame, text=currentVisitors[i], command=partial(signOut, topFrame, bottomFrame, currentVisitors[i]))
buttonDictionary[i].pack()
我已经看到这样做的另一种方法,但是没有尝试,是每次i
将lambda
分配给一个新变量:
command=lambda i=i: signOut(topFrame, bottomFrame, currentVisitors[i])
当我第一次使用循环中的lambdas开始使用Python时,我已经不止一次烧坏了(包括一个与此类似的尝试在循环中为动态生成的按钮分配回调的情况)。我甚至创建了一个片段,只要我输入think_about_it('are you sure you want to use a lambda?')
就会扩展到lambda
,只是为了提醒我自己带来的痛苦......