Python闭包,默认参数不等于使用functools.partial?

时间:2011-11-06 21:02:13

标签: python lambda closures pyqt4 partial

我正在使用PyQt在Python 3.2中做一个小游戏。我需要在菜单操作中插入几乎相同但具有其他参数的操作。我想我会用lambdas来做,但事实证明所有的动作都有相同的参数。

原来这是一个封闭问题,我根据this post解决了其他问题。但是建议的解决方案之一(使用默认参数)应该与另一个解决方案等效,但是不起作用。当我用打印功能进行一点测试时,两种解决方案都是平等的。

我想了解为什么它在这种情况下有所不同。连接方法是否会以某种方式影响它?它可能与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]

最让我感到惊讶的是,它作为第二个参数传递了错误,好像他评估了a = co?那么使用default参数的闭包与使用partial的不同,它是如何工作的?

1 个答案:

答案 0 :(得分:4)

但如果你写:

[m(False) for m in lambdas]

它将使用参数8,False调用StartGame。

Qt可能用参数False调用你的lambdas,所以lambda的默认参数根本就不用了。

但你的想法很好。请尝试以下操作:

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

现在只需忽略False并使用real_co值。