我有一个简单的问题。我有一个列表(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()
答案 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)
在这种情况下,read
和i
都会被查找以进行partial
调用,并且不会有全局加载,因此不会保留{{1}的局部变量活着的。