42

forループ内で tkinter にボタンを作成しようとしています。そして、各ループで、iカウント値をコマンド値の引数として渡します。そのため、関数が値から呼び出されると、commandどのボタンが押されたかを判断し、それに応じて動作することができます。

問題は、長さが 3 だとすると、タイトルGame 1を含む 3 つのボタンが作成Game 3されますが、いずれかのボタンを押すと、出力される値は常に2最後の反復です。したがって、ボタンは個別のエンティティとして作成されているiように見えますが、コマンド引数の値はすべて同じようです。コードは次のとおりです。

def createGameURLs(self):
    self.button = []
    for i in range(3):
        self.button.append(Button(self, text='Game '+str(i+1),
                                  command=lambda: self.open_this(i)))
        self.button[i].grid(column=4, row=i+1, sticky=W)

def open_this(self, myNum):
    print(myNum)

iその特定のボタンに固執するために、反復ごとに現在の値を取得する方法はありますか?

4

3 に答える 3

109

ラムダを に変更しますlambda i=i: self.open_this(i)

これは魔法のように見えるかもしれませんが、これが起こっていることです。そのラムダを使用して関数を定義する場合、 open_this 呼び出しは、関数を定義する時点で変数 i の値を取得しません。代わりに、クロージャーを作成します。これは、「呼び出された時点での変数 i の値を探す必要がある」というメモのようなものです。もちろん、関数はループが終了した後に呼び出されるため、その時点で i は常にループの最後の値と等しくなります。

このi=iトリックを使用すると、関数は、後で i の値を検索するのを待つ代わりに、ラムダが定義された時点で i の現在の値を格納します。

于 2012-06-02T19:15:21.677 に答える
8

これが Python でのクロージャの仕組みです。私は一度この問題に遭遇しました。これに使用できますfunctools.partial

for i in range(3):
    self.button.append(Button(self, text='Game '+str(i+1), command=partial(self.open_this, i)))
于 2012-06-02T19:13:41.307 に答える