2015-01-14 59 views
1

將一個lambda函數連接到一個Qt小部件,lambda需要捕獲兩個局部變量並將它們傳遞給一個外部函數。我有多數民衆贊成絆倒了我一個問題,因爲它是絕對位置:本地變量的第一個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_answercorrect_answer,並且在調用lambda函數之前插入的print()語句確認兩個變量都設置爲所需的字符串。也許我只是沒有正確捕獲變量,但在做了一些閱讀後,我找不到任何與我的語法有關的問題。我的變量捕捉看起來與我發現的衆多示例相同。

+1

嘗試打印字符串的'repr',有可能是你看不到的東西 –

+0

@ Padraic Cunningham:謝謝你的建議,但是這兩個字符串的repr只是預期的字符串。 –

+1

您是否可以以獨立的方式重現問題(理想情況是獨立於Qt的問題)? – BrenBarn

回答

1

您總是看到False作爲第一個參數傳入您的回調lambda,因爲Qt定義信號QAbstractButton::clicked採用默認值爲False的單個參數。由於您的lambda正在處理該信號,因此將使用False進行調用。

爲了其他人的利益:因爲lambda只被一個參數調用,所以第二個和第三個參數獲得它們的默認值,OP現在定義爲範圍內變量answercurrent_answer的值。

1

我敢肯定它只是下面:

當我們在函數定義f(keyword=default...)定義默認參數,但在電話裏,我們都沒有明確申明keyword=value那麼它關心的參數順序,即使他們似乎與關鍵字匹配。所以我相信你的lambda函數關心它接收的順序,而不是你分配的默認值。在你的第一個例子中,ca得到第一個參數發送給lambdaa得到的任何第二個參數。在你的第二個例子中,獲取第一個參數是aca獲得第二個參數。你爲他們定義了默認值的事實是沒有做任何事情,除非任何正在調用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=False,b=True,因爲當我以這種方式調用它時,它會理解該調用的第一個參數是a,第二個參數是b

如果我使用了第三個選項(這是我想你期待)

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

然後我得到x=Truey=False。我認爲這是你認爲你會得到的行爲。

+0

我很欣賞這個建議,但這個問題似乎與Qt進行lambda捕獲有關。我的代碼中沒有任何時候顯式設置要捕獲的變量中的任一個爲布爾值。 –

+1

我並不是建議你將任何變量都明確地設置爲布爾值。在我的例子中,我可以很容易地使用'3'和'4'而不是'True'和'False'。關鍵是,無論是調用'lambda'函數發送它的參數。這些論據會覆蓋你試圖分配的默認值。 – Joel

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所寫入的變量剛剛被被調用的函數忽略,代碼工作。

如果我添加一個打印(sacrificial_variable)調用ap.parse_answer(),毫不奇怪它的值是False。

+1

鑑於此,爲什麼根據默認值發送lambda參數?只要做'lambda x:self.ap.parse_answer(current_answer,correct_answer)' – Joel

+1

@Joel:我創建了多個按鈕,迭代地連接着不同的函數。我的代碼原本就是按照您的建議使用的,但是將相同的功能(生成的最終代碼)連接到所有創建的按鈕上。 –

+0

只是要小心你的方法 - 如果任何調用會發送兩個參數,你的'a'會再次被覆蓋。 – Joel

相關問題