我一直在编写一个跟踪家庭作业的软件,用python编写。我将给出一个显示所有作业的小片段。
def delHomework(homework,element,HLabel,HDelete):
del homework.get(element)
HLabel.destroy()
HDelete.destroy()
row = 0 #keeps track on which height everything is inserted
for i in homeworks: #homeworks is a list of all homework's
HLabel = Label(text=i) #displays the homework
HLabel.grid(column=0,row=row)
HDelete = Button(text="delete",command=lambda:
delHomework(homework,i,HLabel,HDelete)
#is the button to delete the homework
HDelete.grid(column=1,row=row)
row += 1
问题是,即使它全部正确显示,当你尝试删除任何作业时,最后一个被删除而不是相关的一个,因为lambda引用变量的最新状态而不是那个迭代而我不能弄清楚如何使它工作。希望这个问题有道理。
答案 0 :(得分:1)
假设HDelete
缺少副作用只是一个复制粘贴问题。
实际问题是,i
的值不是为lambda函数计算的,直到函数被调用,并且当它被调用时,它使用最新值i
,在此case,这将是i
列表中homworks
的最后一个值。
一个非常简单的例子 -
>>> lst = [1,2,3,4,5,6]
>>> newlst = []
>>> for i in lst:
... newlst.append(lambda : print(i))
...
>>> newlst[1]()
6
>>> newlst[2]()
6
您应该将元素作为默认参数传递给lambda
。示例 -
HDelete = Button(text="delete",command=lambda ele = i, hl = HLabel, hd = HDelete:
delHomework(homework,ele,hl,hd))
显示其工作的示例/演示 -
>>> lst = [1,2,3,4,5,6]
>>> newlst = []
>>> for i in lst:
... newlst.append(lambda ele = i: print(ele))
...
>>> newlst[2]()
3
>>> newlst[1]()
2
答案 1 :(得分:0)
正如以下问题中的回答中所解释:What do (lambda) function closures capture?
你可以这样做:
HDelete = Button(text="delete",command=(lambda i, l, d: lambda:
delHomework(homeworks, i, l, d))(i, HLabel, HDelete)
或类似的东西:
def createDeleteCommand(homeworks, i, l, d):
return lambda: delHomework(homeworks, i, l, d)
HDelete = Button(text="delete",command=
createDeleteCommand(homeworks, i, HLabel, HDelete))