1

基本的に、ループで作成される一連の OptionMenus がありますが、現在は空です。

option_menu = []
for ii in range(jj):
    option_menu.append([])  
    for ll in range(kk):   
        option_menu[ii].append(OptionMenu(frame,tkinter_text_var[ii][ll],''))

次に、チェックボックスを使用して、次の行に沿って値を設定します。

for ii in range(jj):
    for ll in range(kk):   
        option_menu[ii][ll]["menu"].add_command(label = name_from_box.get(), command = lambda: tkinter_text_var[ii][ll].set(name_from_box.get()))

これはすべての OptionMenus を適切に設定するように機能しますが、OptionMenus のいずれかで値を選択すると、option_menu[jj][kk] (つまり、最後に作成されたもの) のみが設定されます。

それで、私は何を間違ったのですか?

4

1 に答える 1

4

これは、クロージャーに関連する非常に一般的な質問です。次の例を見てください。

alist = [lambda : x for x in range(10) ]
print (alist[2]()) #9
print (alist[4]()) #9

すべて 9 になります。なぜですか。各ラムダ関数は変数を参照するためですxxループの繰り返しごとに変更されますが、それらはすべて同じオブジェクトを参照しています

これを回避する 1 つの方法は、デフォルトの引数を使用することです。デフォルトの引数は、関数が呼び出されたときではなく、関数が作成されたときに評価されます。

alist = [lambda y=x: y for x in range(10) ]
print (alist[2]()) #2
print (alist[4]()) #4

(同じことを行う別の方法には、functools.partial時々見られるものがあります...)

私はよく言うのが好きです - 「閉鎖に注意してください」。彼らは少しトリッキーかもしれません。

于 2012-08-03T18:24:12.987 に答える