2016-12-06 70 views
0

它在tkinter中。最后一行将x = len(FRAME_LIST)“Buttons”添加到下拉菜单中。问题是它们都引用同一帧(FRAME_LIST中的最后一帧)。如何让每个按钮都引用FRAME_LIST中的不同帧?如何用for循环制作按钮

for F in FRAME_LIST: 
     frame = ChallengePage(mainframe,self, F) 
     self.frames[F] = frame 
     frame.grid(row = 0, column = 0, sticky = "nsew") 
     subMenu1.add_command(label = F.id, command = lambda: self.show_frames(F)) 

编辑: 所以更准确地说,当我遇到这个问题,我想好了,问题是我需要声明一个局部变量,所以我尝试这样的:

 A = F 
     subMenu1.add_command(label = F.id, command = lambda: self.show_frames(A)) 

但它没有工作,即使A被声明为内部循环,并在每个循环中重新声明,它仍然会得到相同的结果。

我现在碰到的链接:https://docs.python.org/3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result

它显示了解决方案:

 subMenu1.add_command(label = F.id, command = lambda A = F: self.show_frames(A)) 

不知何故神奇地工作,但我不明白为什么它是从我的本地A.任何不同势

回答

0

在循环中使用lambda时,这是一个常见问题。我通常使用一个partial代替:

from functools import partial 

for F in FRAME_LIST: 
    frame = ChallengePage(mainframe, self, F) 
    self.frames[F] = frame 
    frame.grid(row=0, column=0, sticky="nsew") 
    subMenu1.add_command(label=F.id, command=partial(self.show_frames, F)) 

因为:closures

总结:在循环的lambda会记住名称的变量(F)的,而不是它指向的每次循环的价值。在点击按钮并触发命令时,名称F指向for循环迭代中的最后一个值,所以这将传递给lambda。另一方面,Partials知道F在每次迭代时指向的对象,并跟踪它,以便使用适当的参数调用self.show_frames()