這是Python中常見的問題,它是沒有直接關係的Tkinter:
讓我們來看看這個代碼:
i = 0
def foo():
# here i will be lookup in the global namespace *when foo will be executed*
print i
foo() # => 0
i = 1
foo() # => 1
# if we want to force the "evaluation" of i at function definition,
# we have to put it in the function definition
def bar(i=i):
# here i is the function argument, and it default value is the value of the "global i" at the time the function was defined
print i
bar() # => 1
i=2
bar() # => 1
foo() # => 2
在你的情況,這是同樣的問題,但與拉姆達(和lambda表達式是函數) 的「i」的拉姆達在拉姆達(當所有checkbuttons是執行時作出的評價創建和我== 9)
所以,你必須確定你的命令參數是這樣的:
l = ttk.Checkbutton(root, text ="",variable=checkData[i],command=lambda i=i: onCheck(conditionID[i],checkData[i]), onvalue=True, offvalue=False)
,或者如果你想更明確的:
l = ttk.Checkbutton(root, text ="",variable=checkData[i],command=lambda index=i: onCheck(conditionID[index],checkData[index]), onvalue=True, offvalue=False)
以上在:
for i in range(0,10):
checkData.append(BooleanVar())
conditionID.append(i)
# we define a new function (10 times)
# i is resolve at function definition (now)
def call_onCheck(index=i):
# the arguments of onCheck are resolved at function execution.
# it will take what is in the lists at the execution time.
# it may change or not (in your case : not)
return onCheck(conditionID[index], checkData[index])
l = ttk.Checkbutton(root, text ="",variable=checkData[i],command=call_onCheck, onvalue=True, offvalue=False)
w=Message(root,background='ivory',text="test" + str(i),width=60)
l.grid(column=1,row=i+1)
w.grid(column=2,row=i+1)
由於該列表的內容不會改變*(在您提供的代碼中),您還可以編寫:
from Tkinter import *
import tkMessageBox
import ttk
root = Tk()
# Those lists are not strictly necessary, but you may want to check this list from other function, So I keep it
checkData = []
# Here you store i the the i index of the list. I'm pretty sure this list is not necessary
conditionID = []
def onCheck(conditionID,checkData):
print checkData.get()
print conditionID
for i in range(0,10):
boolVar = BooleanVar()
checkData.append(boolVar)
conditionID.append(i)
l = ttk.Checkbutton(root,
text ="",
variable=boolVar,
# we don't need to add a "resolution step" at execution as the values we will need are already known at lambda definition
command=lambda boolVar=boolVar, i=i : onCheck(i, boolVal)),
onvalue=True, offvalue=False)
w=Message(root,background='ivory',text="test" + str(i),width=60)
l.grid(column=1,row=i+1)
w.grid(column=2,row=i+1)
root.mainloop()
*列表中的布爾值會改變,但它是同一個booleanVar對象,所以從列表的角度來看,值不會改變。
謝謝大家的答案。我對Python很陌生,這種與函數的交互對我來說是新的。只是爲了澄清,當我給每個lambda賦值時,我實際上設置了10個函數,每個函數都與'i'相關聯的硬件集/鎖定值,conditionID [i]變爲i = 1的conditionID [1],並且任何值傳入lambda是conditionID [1]的值,不再連接到列表conditionID [1]? – Mathieas
(我已經更新了我的答案。)是的,你創建了10個函數,你沒有連接到我,但你仍然連接到列表的conditionID。我最後的代碼命題與列表完全無關。 – mgautierfr