Lambda在for循环中使用时传递错误的参数

地图

我正在建立一个GUI,您可以在其中按下按钮来隐藏元素。为了构建此功能,我遍历了dict包含按钮和元素的,并用于lambda连接方法并传递相应的参数。但是由于某种原因,这不能正常工作。所有lambda功能都只使用最后一个参数,我觉得这很奇怪。这里发生了什么?lambda循环中的所有都指向同一对象并被连续覆盖吗?对于我为什么会是这种情况,这真的没有任何意义。

我发现的解决方法是functools.partial改用,但我仍然想知道为什么使用lambda不起作用。

这是一个例子:

import sys
from functools import partial
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton, QLabel, \
    QVBoxLayout


class Test(QDialog):
    def __init__(self):
        super().__init__()
        lay = QVBoxLayout(self)
        self.setLayout(lay)
        button1 = QPushButton('Button1')
        label1 = QLabel('Button1')
        button2 = QPushButton('Button2')
        label2 = QLabel('Button2')
        lay.addWidget(button1)
        lay.addWidget(label1)
        lay.addWidget(button2)
        lay.addWidget(label2)

        hide_buttons = {
            button1: label1,
            button2: label2,
        }
        for button, label in hide_buttons.items():
            # for some reason, this passes on the wrong arguments!
            button.clicked.connect(lambda: self.hide_label(button, label))
            # button.clicked.connect(partial(self.hide_label, button, label))

    @pyqtSlot(QPushButton, QLabel)
    def hide_label(self, button, label):
        print(button.text(), label.text())
        label.hide() if label.isVisible() else label.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    dialog = Test()
    dialog.show()
    sys.exit(app.exec_())
蒂埃里·拉图耶(Thierry Lathuille)

问题是,当lambda表达式得到执行,他们将使用的电流值buttonlabel,这是他们最后的循环过程中得到的。

在lambda被定义(而不执行)时捕获变量值的常见技巧是使用默认参数,因为它们总是在定义时求值:

for button, label in hide_buttons.items():
    button.clicked.connect(lambda _, button=button, label=label: self.hide_label(button, label))

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章