lambda in for loop принимает последнее значение

Архив # / USR / бен / окр питон! Импорт Tkinter , как ки импорта TTK из TkTreectrl импорта MULTILISTBOX класса SomeClass ( TTK . Кадры ): четкости __init__ ( я , * аргументы , ** kwargs ): TTK . Рамка . __init__ ( самостоятельно , * арг , ** kwargs ) самостоятельно . пакет ( expand = True , fill = tk . ОБА ) самостоятельно . grid_rowconfigure ( 0 , weight = 1 ) self . grid_columnconfigure ( 0 , weight = 1 ) self . View = MultiListbox ( self ) __columns = ( "Дата" , "Время" , "Тип" , "Файл" , "Линия", "-" , "Функция" , "сообщение" ) самостоятельно . Просмотр . configure ( columns = __columns , expandcolumns = ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 )) self . Просмотр . связывать ( "" , сам . cell_context ) самостоятельно . Просмотр . сетка ( строка = 0 , столбец = 0 , липкий = tk . NW + tk . SE ) self . __recordset = [] self . __recordset_filtered = False # Некоторые фиктивные значения self . __recordset . append ([ "Date" , "Time" , "INFO" , "File" , "12" , "-" , "Function" , "Message Info" ]) self . __recordset . append ([ "Date" , "Time" , "DEBUG" , "File" , "12" , "-" , "Function" , "Message Info" ]) self . __recordset . append ([ "Date" , "Time" , "WARNING" , "File" , "12" , "-" , "Function" , "Message Info" ]) self . __refresh () def cleanView ( self ): self . Просмотр . delete ( 0 , tk . END ) def __refresh ( self ): self . cleanView () для строки в себе . __recordset : self . Просмотр . Вставить ( tk . END , * row ) def filter_records ( self , column , value ): print ( «Фильтровать список записей журнала по {column} и {value}" . format (** locals ())) # Функция фильтра работает должным образом # [...] def cell_context ( self , event ): __cMenu = tk . Меню ( self , tearoff = 0 ), если оно само . __recordset_filtered : __cMenu . add_command ( label = "Show all" , command = lambda : filter_records ( 0 , "" )) else : column = 2 options = [ "INFO" , "WARNING" , "DEBUG" ] для i в диапазоне ( len ( options ) ): option = options [ i ] __cMenu . add_command ( label = "{}" , format ( опция ), command = lambda : self . filter_records ( column , option )) # Также попытался использовать для опции в параметрах здесь с тем же результатом, что и сейчас __cMenu . пост ( событие . x_root , событие . y_root ) , если __name__ == "__main__" : корень = тк . Тк () приложение = SomeClass ( корень ) корень . mainloop ()

Контекстное меню должно динамически отображать переменные фильтра и выполнять функцию с параметрами, определенными внутри обратного вызова. Общие описания отображаются правильно, но вызов функции всегда выполняется с последними установленными funcs = [ lambda : i для i в диапазоне ( 3 )] для f в funcs : print ( f ()) .

То, что я пробовал:

funcs = [lambda i=i:i for i in range(3)]
for f in funcs: print(f())

Текущий выход я получаю:

Фильтрация записей журнала на 2 и DEBUG

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

Любая помощь рекомендуется.

python,lambda,tkinter,contextmenu,

3

Ответов: 1


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

__cMenu.add_command(label="{}".format(option),
    command=lambda: self.filter_records(column, option))

печатает «2» 3 раза, потому что 3 функции идентичны, а «i» в каждом не оценивается до вызова, когда i == 2. Однако,

option=option

выполняет три различные функции, каждая из которых имеет другое фиксированное значение, поэтому печатаются 0, 1 и 2. В вашем заявлении

:

добавьте optionранее, :чтобы записать различные значения option. Вы можете переписать как

lambda opt=option: self.filter_records(column, opt)

для дифференциации переменной цикла из параметра функции. Если columnизменить в цикле, это потребует такого же лечения.

питон, лямбда, Tkinter, ContextMenu,
Похожие вопросы