用tkinter统一python“for”

时间:2017-08-28 11:12:24

标签: python python-2.7 for-loop tkinter

我有一个简单的问题。我有一个列表(l1)的值,我希望它为列表中的每个值创建Button,它将值添加到textvariable(tkvar)。程序生成按钮,但每个按钮都添加列表的最后一个值。如何根据他的位置使该按钮为“tkvar”添加正确的值?

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 个答案:

答案 0 :(得分:1)

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

您已经运行了一个循环,您可以使用lambda创建闭包。在for循环结束很久之后,这些调用中的每一个调用read(i)i来自phase的范围。

一种解决方法是获取i的值并将其作为默认参数存储在lambda中:

lambda i=i: read(i)

这将存储i在函数的默认参数中创建lambda时的值。我们可以检查函数的不同行为:

>>> 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

部分应用程序可能更干净,完全替换lambda:

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

在这种情况下,readi都会被查找以进行partial调用,并且不会有全局加载,因此不会保留{{1}的局部变量活着的。