python - 为什么 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
为什么会发生?
解决方案
关于变量定义,for
循环不会创建单独的范围,因此i
lambda 内部的变量不是它的本地变量,它是在外部范围中定义的。这意味着它超出了 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]))
推荐阅读
- regex - 正则表达式匹配帮助?空格后关闭
- php - 如何使用Prepared Statements知道用户名是否已经在PHP的数据库中?
- android - 在 Android 中重新激活 Camera2
- python - How to encode json dump correctly in python
- swift - 如何从 Swift 泛型函数中捕获参数
- android - ViewBinding 的 Master/Detail Flow 问题
- python - 使用蓝图和命名空间时,Flask RESTPlus API URL not found 错误 - 404 not found 错误
- python - 使用 pandas 数据框复制和重命名文件
- python-3.x - 通过 Pyenv 安装 Python 3.x 的问题
- google-apps-script - 如何从 Google Apps 脚本将具有名称的成员添加到组中?