При изменении переменной меняется и аргумент в lambda python

Я получаю информацию из файла, а потом вызываю функцию select_user. Вот упрощённая версия кода:

from tkinter import * # Использую tkinter для графического интерфейса

a_txt = open("a.txt", encoding = "utf8").read() # Читает файл a.txt
a = {}
for i in a_txt.split("\n"): # При каждой строке файла выполняет следующее
    a_tab = a.split("\t")
    a[a_tab[0]] = a_tab[1] # Обнаруживая таб в файле, разделяет его на две части и записывает в a

tk = Tk()

def select_user(clid):
    print(clid)

for name, clid in a.items():
    b = Button(tk, text = name, command = lambda: select_user(clid)) # Создаёт кнопку
    b.place(relx = 0.034, rely = 0.08) # Размещает кнопку на экране (в оригинальном коде они помещаются на экран в разные места)

Вот файл a.txt (вместо четырёх пробелов там табы):

Название1    0
Название2    1
Название3    2

Проблема заключается в том, что аргумент clid изменяется с каждой итерацией for и при нажатии кнопки передаётся самый последний результат. Вот результат нажатия на 3 разные кнопки:

2
2
2

Есть ли возможность как-нибудь по другому вызвать функцию с аргументом (и чтобы аргумент не менялся) при нажатии кнопки в tkinter?

Надо сделать так, чтобы при нажатии на первую кнопку чтобы результатом был 0, на вторую 1, а на третью 2


Ответы (1 шт):

Автор решения: gil9red

Это поведение особенность лямбд при циклах. Чтобы обойти проблему нужно в лямбде значение задавать как параметр с значением, поэтому вместо lambda: select_user(clid) нужно писать lambda clid=clid: select_user(clid) (т.е. мы объявили лямбду с параметром clid, у которого значение по-умолчанию берется из переменной clid)

Пример:

b = Button(tk, text = name, command=lambda clid=clid: select_user(clid))
→ Ссылка