局部变量的第一个lambda捕获始终为False

时间:2015-01-14 22:48:59

标签: python python-3.x lambda

将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_answercorrect_answer分配False,并且在调用lambda函数之前插入的print()语句确认两个变量都是设置为所需的字符串。也许我只是没有正确捕获变量,但在做了一些阅读之后我发现我的语法没有任何问题。我的变量捕获与我找到的众多示例看起来相同。

3 个答案:

答案 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=Trueb=False

但如果我把它称为

a=True
b=False
(x,y) = f(b,a)

我会找到x=Falseb=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。