【问题标题】:What's wrong with this lambda (maybe something to do with PyQt?) [duplicate]这个lambda有什么问题(可能与PyQt有关?)[重复]
【发布时间】:2020-12-21 16:34:22
【问题描述】:

我将三个按钮连接到一个函数,该函数接受一个参数并简单地打印它。正如您在下面的 MWE 中所见,按钮以外观不同的方式传递参数,但据我所知,没有任何语义差异。

from PyQt5.QtWidgets import QPushButton, QFrame, QApplication, QVBoxLayout
from functools import partial


def func(i):
    print(i)

app = QApplication([])
frame = QFrame()
layout = QVBoxLayout()
frame.setLayout(layout)

b1 = QPushButton('button 1', frame)
b1.clicked.connect(lambda: func(1))

b2 = QPushButton('button 2', frame)
b2.clicked.connect(partial(func, i=2))

b3 = QPushButton('button 3', frame)
b3.clicked.connect(lambda x=3: func(x))

layout.addWidget(b1)
layout.addWidget(b2)
layout.addWidget(b3)

frame.show()
app.exec()

所以当我点击按钮 1 到 3 时,我希望看到

1
2
3

但是我得到了

1
2
False

最后一个 lambda 有什么问题?这可能是 PyQt 的错误吗?

PyQt 版本为 5.15.2。

【问题讨论】:

  • 您将 x 与返回 false 的 3 进行比较。试试这个:(lambda x: func(x))(3)

标签: python python-3.x pyqt5


【解决方案1】:

我相信这是因为 PyQt 将参数传递给连接函数。从 QPushButton 继承的 documentation for QAbstractButton 中,clicked 插槽(PyQt 中的信号回调称为插槽)将接收 checked 参数,这是一个布尔值。 lambda 函数lambda x=3: func(x) 采用一个参数x,它采用默认值3。如果没有参数传递给此槽,x 将因此采用值3。但是,PyQt 将False 传递给此函数,正如clicked 信号文档中指定的那样,所以x 取而代之的是False

【讨论】:

  • 感谢您的快速回复。不过,Maxime Chéramy 的回答甚至更快(如果我们计算 cmets,则与您的回答相同),所以我接受了他的回答。
  • 我对这个答案做了+1,因为我知道它总是受到赞赏:)。
【解决方案2】:

您创建一个具有默认值的 lambda:

lambda x=3: func(x)

但 Qt 将 False 传递给它(checked 参数),因此不使用默认参数。

【讨论】:

  • 为什么lambda: func(1) 没有失败呢? Qt 是否检查函数是否接受参数?
  • 在这种情况下,lambda 不使用参数并使用值1 调用 func。这与使用默认值不同。
  • 不使用是什么意思?为什么它不会像(lambda: func(1))(False) 那样失败,TypeError: <lambda>() takes 0 positional arguments but 1 was given
  • 我认为如果回调不带参数,Qt 不会传递参数,以使框架更易于使用。
  • PyQt 总是调用一个槽,无论它的参数是否少于信号提供的参数。如果信号有两个参数并且函数只接受一个参数,则无论如何都会使用第一个信号参数调用该函数。如果函数不接受参数,则在发出信号时无论如何都会调用它,即使它有参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 1970-01-01
  • 2022-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-17
相关资源
最近更新 更多