2015-11-29 54 views
0

版問題:拉姆達在循環只需要最後一個值

上下文菜單應該動態顯示過濾變量,並在回調中定義的參數執行的功能。 通用描述顯示正確,但函數調用始終使用上次設置選項執行。

我曾嘗試:

#!/usr/bin/env python 

import Tkinter as tk 
import ttk 
from TkTreectrl import MultiListbox 

class SomeClass(ttk.Frame): 
    def __init__(self, *args, **kwargs): 
     ttk.Frame.__init__(self, *args, **kwargs) 
     self.pack(expand=True, fill=tk.BOTH) 

     self.grid_rowconfigure(0, weight=1) 
     self.grid_columnconfigure(0, weight=1) 

     self.View=MultiListbox(self) 

     __columns=("Date","Time","Type","File","Line","-","Function","Message") 
     self.View.configure(columns=__columns, expandcolumns=(0,0,0,0,0,0,0,1)) 

     self.View.bind("", self.cell_context) 
     self.View.grid(row=0, column=0, sticky=tk.NW+tk.SE) 

     self.__recordset   = [] 
     self.__recordset_filtered = False 

     #Some dummy values 
     self.__recordset.append(["Date", "Time", "INFO", "File", "12", "-", "Function", "Message Info"]) 
     self.__recordset.append(["Date", "Time", "DEBUG", "File", "12", "-", "Function", "Message Info"]) 
     self.__recordset.append(["Date", "Time", "WARNING", "File", "12", "-", "Function", "Message Info"]) 

     self.__refresh() 

    def cleanView(self): 
     self.View.delete(0, tk.END) 

    def __refresh(self): 
     self.cleanView() 
     for row in self.__recordset: 
      self.View.insert(tk.END, *row) 

    def filter_records(self, column, value): 
     print("Filter Log Recordset by {column} and {value}".format(**locals())) 
     # Filter functionality works as expected 
     # [...] 

    def cell_context(self, event): 
     __cMenu=tk.Menu(self, tearoff=0) 

     if self.__recordset_filtered: 
      __cMenu.add_command(label="Show all", command=lambda: filter_records(0, "")) 

     else: 
      column=2 
      options=["INFO", "WARNING", "DEBUG"] 

      for i in range(len(options)): 
       option=options[i] 
       __cMenu.add_command(label="{}".format(option), command=lambda: self.filter_records(column, option)) 
      # Also tried using for option in options here with same result as now 
     __cMenu.post(event.x_root, event.y_root) 

if __name__=="__main__": 
    root=tk.Tk() 
    app=SomeClass(root) 
    root.mainloop() 

電流輸出我得到的是:

過濾日誌記錄由2和DEBUG

無論哪三個我選擇的選項。我認爲它只能處理最後一個選項的垃圾回收,但我無法弄清楚如何避免這種情況。

建議任何幫助。

回答

4

請閱讀關於minimal examples。如果沒有閱讀你的代碼,我相信你遇到了一個衆所周知的問題,在以前的問題和答案中需要2行來說明。當函數被執行時,函數體中的名字被評估。

funcs = [lambda: i for i in range(3)] 
for f in funcs: print(f()) 

打印「2」 3倍,因爲3個功能是相同的,所述的「i」中的每個未評價,直到呼叫,當我== 2。然而,

funcs = [lambda i=i:i for i in range(3)] 
for f in funcs: print(f()) 

提出了三個不同的功能,每個功能都具有不同的捕捉值,因此打印0,1和2。在你的聲明

__cMenu.add_command(label="{}".format(option), 
    command=lambda: self.filter_records(column, option)) 

:前添加option=option捕捉option不同的值。您可能需要重寫爲

lambda opt=option: self.filter_records(column, opt) 

以區分循環變量和函數參數。如果在循環內更改column,則需要進行相同的處理。