首页 > 解决方案 > 为什么 add_command 中的语句不能正常工作?

问题描述

我试试这个:

def prints(string):
print(string)

from tkinter import *
root = Tk()
menu = Menu(root)
filemenu = Menu(menu, tearoff=0)
List = Menu(filemenu, tearoff=0)

labels=[x for x in range(1,4)]

for i in range(len(labels)):
    List.add_command(label=labels[i], command=lambda: prints(labels[i]))
List.add_command(label="!", command=lambda: prints("!"))
List.add_command(label="@", command=lambda: prints("@"))
List.add_command(label="#", command=lambda: prints("#"))
filemenu.add_cascade(label="List", menu=List)
menu.add_cascade(label="File", menu=filemenu)

root.config(menu=menu)
root.mainloop()

它显示: 图像

当我点击 !,@,# 它打印 !,@,#

但是当我点击 1,2,3 它打印 3,3,3 而不是 1,2,3

为什么会发生?

标签: pythontkinter

解决方案


关于变量定义,for循环不会创建单独的范围,因此ilambda 内部的变量不是它的本地变量,它是在外部范围中定义的。这意味着它超出了 for 循环的末尾,保留了最后一个值(在您的示例中为 3)。

lambda 定义存储了您要访问的事实i,它没有存储定义时的i获取其值的实际访问i发生在运行lambda时,而不是在 定义lambda 时,这就是您总是看到 3 的原因。

通常的技巧是在定义时通过将值存储在 lambda 的本地变量中来捕获值,通常是通过添加一个参数:

for i in range(len(labels)):
    List.add_command(label=labels[i], command=lambda j=i: prints(labels[j]))

推荐阅读