2016-12-06 101 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()