2015-08-31 3 views
1

Я пишу часть программного обеспечения, которое отслеживает домашнюю работу, написанную на питоне. Я дам небольшой фрагмент, который отображает все домашние задания.Python Homework

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 

Проблема заключается в том, что даже если он все работает правильно, при попытке удалить любую домашнюю работу, последний удаляется вместо соответствующих одному, потому что лямбда-ссылка на новейшем насытить переменный вместо на этой итерации Я не могу понять, как заставить его работать. Надеюсь, этот вопрос имеет смысл.

ответ

1

Предполагая, что недостающая паратезис для HDelete является только копией.

Фактическая проблема заключается в том, что значение i не вычисляется для лямбда-функции до тех пор, пока функция не будет вызвана, и когда она вызвана, она использует последнее значение i, в этом случае это будет последний значение 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)) 

Пример/Demo, чтобы показать свою работу -

>>> 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 
+0

Спасибо, что я искал. – Lcoder

0

Как объяснен в ACCPETED ответа на на следующих вопросах: 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)) 
Смежные вопросы