2012-06-12 88 views
3

(作爲「功課」標籤表示,這是計算機科學項目的一部分。)Python和Tkinter的lambda函數

我寫一個危害!用tkinter模擬Python,我在使用按鈕中的lambda函數時遇到了一個很大的問題。假設root = Tk()categories是一個列表。

# Variable to keep the buttons 
root._buttons = {} 

# Display headers on top of page 
for i in range(5): 
    # Get category name for display in main window 
    name = categories[i] 
    b = Label(root, text=fill(name.upper(), 10), width=18, height=3,\ 
     bg="darkblue", fg="white", font=("Helvetica bold", "", 11)) 
    b.grid(row=0, column=i) 

    # Create list of buttons in that variable (root._buttons) 
    btnlist = [None]*5 

    # Display individual questions 
    for j in range(5): 

     # Make a button for the question 
     b = Button(root, text="$" + str(200 * (j+1)), width=8, height=1, 
      bg="darkblue", fg="orange", font=("Impact", "", 30)) 
     b.cat = name 
     b.value = 200 * (j + 1) 
     b.sel = lambda: select(b.cat, b.value) 

     # Add callback event to button 
     print(b.cat, b.value, b.sel) 
     b.config(command=b.sel) 

     # Add button to window 
     b.grid(row=j+1, column=i) 

     # Append to list 
     btnlist[j] = b 

    root._buttons[categories[i]] = btnlist 

對於所有的代碼,看到my little Code Viewer (under construction!)

這是在lambda: select(b.cat, b.value)哪裏出了問題,似乎發生,因爲當我點擊板上的任何按鈕,它總是轉到最後一個按鈕董事會。我嘗試了其他方法,不幸的是全部使用lambda,我還沒有看到任何不涉及lambda的方法。

回答

8

變化

lambda: select(b.cat, b.value) 

lambda b = b: select(b.cat, b.value) 

在你的原代碼,b不是lambda的局部變量;它在封閉的範圍內被發現。一旦for-loop完成,b保留最後一個值。這就是lambda功能都使用最後一個按鈕的原因。

如果將lambda定義爲帶一個默認值的參數,則默認值在lambda爲時定義爲時確定(並固定)。現在blambda的局部變量,並且當不帶參數調用lambda時,Python將b設置爲默認值,該值默認設置爲各種不同的按鈕。

+0

我一直停留在這個特別的問題3天了。即使我的老師也弄不清楚。非常感謝!! –

0

如果你用函數工廠替換了lambda表達式,它會讓你更有表現力。 (假設你打算多次撥打這個電話)。這樣你就可以在稍後進行分配,添加更復雜的邏輯等,而不必處理lambda的限制。

例如:

def button_factory(b): 
    def bsel(): 
     """ button associated with question""" 
     return select(b.cat, b.value) 
    return bsel 

給定的輸入bbutton_factory返回調用函數與()返回正是你想要的。唯一的區別是你可以做任務等。

即使它最初可能佔用更多的代碼行,它在稍後會給你更大的靈活性。 (例如,您可以將計數器附加到bsel並能夠計算特定問題被選擇的次數等)。

這也有助於反省,因爲你可以使每個文檔字符串明確確定那些質疑它關聯等

+0

我試過你的解決方案,它工作正常,但它不是真的在我的課程範圍之內,所以我不能真正使用它。不過,我也使用'lambda'嘗試了@unutbu的解決方案。不管怎麼說,還是要謝謝你! –