2013-08-29 67 views
0

目前我正在試圖解決在Python的書「巨蟒下一步」,作者並沒有固定,留在代碼中的註釋錯誤starnge行爲:「修復失敗後」通過在Tkinter的一個按鈕傳遞函數參數,在循環

我的第一個解決方案,但通過移除迴路成功的第二個解決方案。問題是我無法弄清楚爲什麼第一個解決方案失敗!

解決方案1:

當用戶單擊使用一個循環,Button對象和一個名爲點擊計算器功能的Tkinter作出的計算器按鈕即可打印從拉姆達參數大寫C。該代碼在我討論的要點上通過違規鱈魚附近的V形符號進行評論。

解決方案2:

刪除生成的按鈕和手代碼每個按鈕反覆循環這個工作和布賴恩Kernighan的建議:得到它使它高效之前先工作!

代碼:

# myCalculator3_final.py 

from Tkinter import * 
from decimal import * 

# key press function: 
def click(key): 
     display.insert(END, key) 


##### main: 
window = Tk() 
window.title("MyCalculator") 

# create top_row frame 
top_row = Frame(window) 
top_row.grid(row=0, column=0, columnspan=2, sticky=N) 

# use Entry widget for an editable display 
display = Entry(top_row, width=45, bg="light green") 
display.grid() 

# create num_pad_frame 
num_pad = Frame(window) 
num_pad.grid(row=1, column=0, sticky=W) 

# This method of passing an argument to click work! Loop removed and buttons hand code 
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
#------------------------------------------------------------------------- 
# create num_pad buttons passing an argument to the command function click 
#------------------------------------------------------------------------- 
seven = Button(num_pad, text="7", width=5, command=lambda :click("7")) 
seven.grid(row=0,column=0) 
eight = Button(num_pad, text="8", width=5, command=lambda :click("8")) 
eight.grid(row=0,column=1) 
nine= Button(num_pad, text="9", width=5, command=lambda :click("9")) 
nine.grid(row=0,column=2) 
four= Button(num_pad, text="4", width=5, command=lambda :click("4")) 
four.grid(row=1,column=0) 
five= Button(num_pad, text="5", width=5, command=lambda :click("5")) 
five.grid(row=1,column=1) 
six= Button(num_pad, text="6", width=5, command=lambda :click("6")) 
six.grid(row=1,column=2) 
one= Button(num_pad, text="1", width=5, command=lambda :click("1")) 
one.grid(row=2,column=0) 
two= Button(num_pad, text="2", width=5, command=lambda :click("2")) 
two.grid(row=2,column=1) 
three= Button(num_pad, text="3", width=5, command=lambda :click("3")) 
three.grid(row=2,column=2) 
zero= Button(num_pad, text="0", width=5, command=lambda :click("0")) 
zero.grid(row=2,column=0) 
#--------------------------------------------------------------------------- 



# calculate the row, column for button 

# create operator_frame 
operator = Frame(window) 
operator.grid(row=1, column=1, sticky=E) 

operator_list = [ 
'*', '/', 
'+', '-', 
'(', ')', 
'C' ] 

# The authors code and I have added the same lambda function as above but 
#it just prints out capital C 
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
r = 0 
c = 0 
for btn_text in operator_list: 
    Button(operator, text=btn_text, width=5, command=lambda: click(btn_text)).grid(row=r,column=c) 
    c = c+1 
    if c > 1: 
     c = 0 
     r = r+1 


##### Run mainloop 
window.mainloop() 

問:

爲什麼拉姆達調用方法點擊傳遞參數的循環不工作,只顯示一個C,但如果我刪除了循環它的工作原理!

回答

2

在此行中:

Button(operator, text=btn_text, width=5, command=lambda: click(btn_text)).grid(row=r,column=c) 

的拉姆達內的btn_text值不會成爲凍結其當前值。相反,當btn_text在循環的下一次迭代中發生變化時,它在lambda中計算的值也會改變。這意味着,所有按鈕的有效有click('C')命令,因爲'C'btn_text最終值。

你可以這樣做:

command=lambda text=btn_text: click(text) 

或者

command=(lambda text: lambda: click(text))(btn_text) 

text將捕獲的btn_text當前值,事後不會改變。你的命令將被正確的參數調用。

+0

你能否解釋一下爲什麼用「C」凍結,我需要在一個新的可變文本捕捉價值:這是與這些循環一般情況下還是因爲我使用的lambda函數。哪種風格更適合維護程序的循環或交叉代碼? –

+0

這種問題幾乎只發生在使用lambdas時。循環是在連續鍵入同樣的事七次最好 - [不要重複自己(http://en.wikipedia.org/wiki/Don%27t_repeat_yourself)是軟件開發的一個重要原則。 – Kevin

+0

你是怎麼知道這個問題的,你能指出我在互聯網上的這個問題的方向(循環中的lambda參數)。我不喜歡代碼,因爲我無法追蹤發生了什麼,如果可能的話,想要參考嗎?非常感謝幫助。 –

相關問題