局部变量的第一个 lambda 捕获始终为 False
First lambda capture of local variable always False
将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,而第二个变量捕获始终是预期的。
这表明我的代码中没有其他东西将 False 分配给 current_answer
或 correct_answer
,并且在调用 lambda 函数之前立即插入的 print() 语句确认了两者变量设置为所需的字符串。也许我只是没有正确捕获变量,但在阅读了一些内容之后,我找不到我的语法有任何问题。我的变量捕获看起来与我发现的许多示例相同。
我很确定它只是以下内容:
当我们在函数定义中定义默认参数时 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
,第二个参数是 b
.
如果我使用第三个选项(这是我认为你所期待的)
(x,y) = f(b=False, a=True)
然后我得到 x=True
、y=False
。我认为这就是您认为会得到的行为。
根据 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。
您总是看到 False
作为传递给回调 lambda 的第一个参数,因为 Qt 定义信号 QAbstractButton::clicked
以采用默认值为 False
的单个参数。由于您的 lambda 正在处理该信号,因此会使用 False
.
调用它
为了其他人的利益:因为 lambda 只用一个参数调用,所以第二个和第三个参数获得它们的默认值,OP 现在将其定义为范围内变量的值 answer
和 current_answer
.
将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,而第二个变量捕获始终是预期的。
这表明我的代码中没有其他东西将 False 分配给 current_answer
或 correct_answer
,并且在调用 lambda 函数之前立即插入的 print() 语句确认了两者变量设置为所需的字符串。也许我只是没有正确捕获变量,但在阅读了一些内容之后,我找不到我的语法有任何问题。我的变量捕获看起来与我发现的许多示例相同。
我很确定它只是以下内容:
当我们在函数定义中定义默认参数时 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
,第二个参数是 b
.
如果我使用第三个选项(这是我认为你所期待的)
(x,y) = f(b=False, a=True)
然后我得到 x=True
、y=False
。我认为这就是您认为会得到的行为。
根据 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。
您总是看到 False
作为传递给回调 lambda 的第一个参数,因为 Qt 定义信号 QAbstractButton::clicked
以采用默认值为 False
的单个参数。由于您的 lambda 正在处理该信号,因此会使用 False
.
为了其他人的利益:因为 lambda 只用一个参数调用,所以第二个和第三个参数获得它们的默认值,OP 现在将其定义为范围内变量的值 answer
和 current_answer
.