Python家庭作业

时间:2015-08-31 17:38:38

标签: python closures

我一直在编写一个跟踪家庭作业的软件,用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引用变量的最新状态而不是那个迭代而我不能弄清楚如何使它工作。希望这个问题有道理。

2 个答案:

答案 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))