将lambda函数连接到Qt小部件,lambda需要捕获两个局部变量并将它们传递给外部函数。我遇到了一个问题,因为它肯定是位置性的:
pushbutton.clicked.connect(lambda ca=current_answer, a=correct_answer:
self.ap.parse_answer(ca, a))
传递(False, "desired correct_answer string")
,同时切换局部变量捕获的顺序:
pushbutton.clicked.connect(lambda a=correct_answer,ca=current_answer:
self.ap.parse_answer(ca, a))
传递("desired current_answer string", False)
我首先捕获的变量始终设置为False,而第二个变量捕获始终是预期的。
这表明我的代码中没有其他内容为current_answer
或correct_answer
分配False,并且在调用lambda函数之前插入的print()语句确认两个变量都是设置为所需的字符串。也许我只是没有正确捕获变量,但在做了一些阅读之后我发现我的语法没有任何问题。我的变量捕获与我找到的众多示例看起来相同。
答案 0 :(得分:1)
我很确定它只是以下内容:
当我们在函数定义f(keyword=default...)
中定义默认参数时,但在调用中我们没有明确说明keyword=value
,那么它关心参数的顺序,即使它们看起来与关键字匹配。因此,我认为您的lambda
功能会关注其接收的顺序,而不是您分配的默认值。在您的第一个示例中,ca
获取第一个参数发送到lambda
的任何内容,a
获取第二个参数。在你的第二个例子中,a
得到第一个参数,ca
得到第二个参数。您为他们定义默认值的事实并不是做任何事情,除非调用lambda
的任何内容都没有发送任何内容。
如果我定义一个函数
def f(a=1,b=2):
return (a,b)
然后将其称为
a=True
b=False
(x,y) = f(a,b)
我会找到x=True
,b=False
但如果我把它称为
a=True
b=False
(x,y) = f(b,a)
我会找到x=False
,b=True
,因为当我以这种方式调用它时,它理解调用的第一个参数是a
,第二个参数是{{1} }。
如果我使用第三种选择(这是我认为你预期的那种)
b
然后我得到(x,y) = f(b=False, a=True)
,x=True
。我认为这是你认为会得到的行为。
答案 1 :(得分:1)
您始终将False
视为传递给回调lambda的第一个参数,因为Qt将信号QAbstractButton::clicked
定义为采用默认值False
的单个参数。由于lambda处理该信号,因此使用False
调用它。
为了他人的利益:因为lambda只用一个参数调用,所以第二个和第三个参数得到它们的默认值,OP现在将其定义为范围内变量answer
的值和current_answer
。
答案 2 :(得分:0)
根据BrenBarn和Lambda Fairy的评论,我决定假设Qt将第一个参数的值重置为False。
作为解决方法,我在ap.parse_answer中添加了第三个位置参数,并且在捕获两个重要变量之前,lambda表达式捕获了一个简单的局部变量:
pushbutton.clicked.connect(lambda sacrificial="",a=answer,ca=current_answer:
self.ap.parse_answer(sacrificial, ca, a))
Qt写入的变量被被调用的函数忽略,代码可以工作。
如果我向ap.parse_answer()添加一个print(sacrificial_variable)调用,毫不奇怪它的值为False。