2017-08-28 10 views
-1

私は簡単な問題があります。私は値のリスト(l1)を持っています。リスト内のすべての値に対してButtonを作成し、textvariable(tkvar)に値を追加します。プログラムボタンを作成しますが、それぞれのリストの最後の値はです。どのようにしてそのボタンを自分の位置に基づいて "tkvar"に適切な値を追加することができますか?tkinterで "for"とunite pythonを組み合わせた

import Tkinter as Tk 
main=Tk.Tk() 
l1=["A", "B", "C"] 
def phase(): 
    for i in l1: 
     Tk.Button(main, text = i, command=lambda: read(i)).pack(side="left") 
    e=Tk.Entry(main, textvariable=tkvar) 
    e.pack() 
    return 
def read(q,*par): 
    tkvar.set(q) 
tkvar=Tk.StringVar() 
phase() 
main.mainloop() 

答えて

1
for i in l1: 
    Tk.Button(main, text = i, command=lambda: read(i)).pack(side="left") 

あなたはlambdaを使用してクロージャを作成し、その中のループを実行しました。呼び出されると、それぞれread(i)が呼び出され、iphaseのスコープから得られます。これはforループの終了後です。

回避策の一つは、iの値を取得し、デフォルトの引数としてラムダ以内にそれを格納することです:

lambda i=i: read(i) 

これは、ラムダは、関数のデフォルト引数の中に作成されたときにiが持っていたことに値を格納します。私たちは、機能の異なる動作を確認することができます。

>>> i=123 
>>> lambda i=i: read(i) 
<function <lambda> at 0x7f8d714b8a28> 
>>> dis.dis(_) 
    1   0 LOAD_GLOBAL    0 (read) 
       3 LOAD_FAST    0 (i) 
       6 CALL_FUNCTION   1 
       9 RETURN_VALUE 
>>> lambda: read(i) 
<function <lambda> at 0x7f8d714b8aa0> 
>>> dis.dis(_) 
    1   0 LOAD_GLOBAL    0 (read) 
       3 LOAD_GLOBAL    1 (i) 
       6 CALL_FUNCTION   1 
       9 RETURN_VALUE 

完全にラムダを交換し、部分的にアプリケーションを実行するためにクリーンであるかもしれない:

from functools import partial 
command = partial(read, i) 

その場合には、両方のreadiを見上げていますpartialを呼び出すと、グローバルな負荷がなくなり、ローカル変数phaseは生きていません。

関連する問題