Анонимная функция lambda: doit(dic[key])
не оценивает key
, пока функция не будет вызвана. К этому времени for-loop
завершено, а переменная for-loop
key
ссылается на последний ключ в dic
.
Когда вызывается анонимная функция (при нажатии кнопки), в глобальном пространстве имен ищется key
, и возвращается текущее значение key
.
Чтобы избежать этой ловушки, вы можете использовать аргумент по умолчанию в выражении lambda
:
for key in dic:
btn = QPushButton(key, self)
btn.clicked.connect(lambda key=key: doit(dic[key]))
vbox.addWidget(btn)
Аргументы по умолчанию оцениваются во время определения , а не во время вызова лямбды. Делая это, key
ищется в локальном пространстве имен анонимной функции, а не в глобальном пространстве имен, и поскольку для значения локального пространства имен для ключа установлено значение по умолчанию, которое отличается для каждого прохода через for цикл, вы получите правильное значение для key
.
Это также объясняется в этом SO ответе .