2011-11-06 5 views
3

私はPyQtを使ってPython 3.2で少しのゲームをしています。私はメニューアクションを挿入する必要がありましたが、これはほぼ同じでしたが、他のパラメータもありました。私はラムダの使用でそれをやることを理解しましたが、すべてのアクションが同じパラメータを持っていることが判明しました。Pythonのクロージャでは、デフォルトの引数はfunctools.partialを使用するのと同じ解決策ではありませんか?

これは閉鎖の問題であることが判明しました。これは他の質問でthis postに従って解決しました。しかし、提案されている解決法(デフォルトの議論を伴う)の1つは、他のものと同等でなければならない。私が印刷機能を使って少しテストをしたところ、両方のソリューションが同等でした。

この場合、なぜ違うのか理解したいと思います。何とかそれに影響を与える接続方法ですか?おそらく、Pythonスコープと関係があります。ここで私は(私は名前とアクションにテキストを割り当てる省略)やっているの抜粋:

cardsOptions = [15, 30, 45, 50, 55, 60, 10] 
self.startActions = [] 
lambdas = [] 
for co in cardsOptions: 
    action = QtGui.QAction(MainWindow) 
    self.menuNewGame.addAction(action) 
    # This works 
    # action.triggered.connect(partial(self.StartGame, 8, co)) 

    lamb = (lambda a = co: self.StartGame(8, a)) 
    lambdas.append(lamb) 

    # This doesn't work, when StartGame is called it gets arguments 8, false 
    action.triggered.connect(lamb) 
    self.startActions.append(action) 

# This proves that closure was done ok, and it saved all co values 
[m() for m in lambdas] 

最も私を驚かせる何が彼が=共同を評価したかのように、第二引数にfalseを渡すということですか?だから、デフォルトの引数でクロージャがpartialと違うのは、このように動作するのでしょうか?

答えて

4

しかし、あなたが書いた場合:

[m(False) for m in lambdas] 

それはあまりにも、偽の引数8、とStartGameして呼び出します。

Qtはおそらく引数がFalseのlambdaを呼び出しているので、lambdaのデフォルト引数は単に使用されません。

あなたの考えは良いです。以下で試してみてください。

lamb = (lambda a, real_co = co : self.StartGame(8, real_co)) 

Falseは単純に無視され、real_co値が使用されます。

+3

[QAction.triggered](http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qaction.html#triggered)シグナルはアクションの 'checked'状態を持ちます。常にTrueまたはFalseのいずれかです。 @slawekが作成しているようなチェック不可能なアクションの場合、チェックされた状態はFalseです。 – Nathan

+0

あなたはそうです、それはうまくいきます。私はそれを考えなかった。その上に、なぜ私はまだ偽がそこにあるのか理解しています。私は誘発されたシグナルには議論がないと思った、私は間違っていた。 PyQt doc: "void triggered(bool = 0)"。それで謎が解き、ここで私のラムダがすべて壊れると思った。ありがとうございました。 編集。あなたの洞察に感謝@Nathan。物事を理解することは常に良いことです: – slawek

関連する問題