为什么变量总是设置为列表中的最后一项?

Why is the variable always set to the last item in the list?

使用 tkinter 和 python 构建一个 GUI,我使用 globals() 添加按钮基于 room_types 的列表。但是,我传递给按钮命令的变量始终是列表中的最后一项,即使使用 room_type[i] 的每个其他实例都与正确的元素相关联。

这就是我遇到的问题。

from tkinter import *

root = Tk()

room_type = ['kitchen', 'living_room', 'bedroom', 'bathroom', 'study', 'laundry', 'dining_room']


def new_room(r):
    print(r)


for i in range(len(room_type)):
    globals()[f'{room_type[i]}_add'] = Button(root, text='Add a ' + room_type[i],
                                              command=lambda: new_room(r=room_type[i]))
    globals()[f'{room_type[i]}_add'].grid(row=1, column=i)

root.mainloop()

它有 7 个按钮,每个按钮都有表示不同房间类型的文本,但出于某种原因,r 始终等于列表中的最后一个元素。在这种情况下,dining_room.

lambda 的使用使另一个函数循环停止在最后一个项目的末尾,因此对于每个循环它都停留在最后一个 i。尝试删除 lambda 并查看。

from tkinter import *

root = Tk()

room_type = ['kitchen', 'living_room', 'bedroom', 'bathroom', 'study', 'laundry', 'dining_room']


def new_room(r):
    print(r)


for i in range(len(room_type)):
    globals()[f'{room_type[i]}_add'] = Button(root, text='Add a ' + room_type[i],
                                              command=new_room(r=room_type[i]))
    globals()[f'{room_type[i]}_add'].grid(row=1, column=i)

root.mainloop()

声明lambda时捕获i的当前值:

from tkinter import *

root = Tk()

room_type = ['kitchen', 'living_room', 'bedroom', 'bathroom', 'study', 'laundry', 'dining_room']


def new_room(r):
    print(r)


for i in range(len(room_type)):
    globals()[f'{room_type[i]}_add'] = Button(root, text='Add a ' + room_type[i],
                                              command=lambda pi=i: new_room(r=room_type[pi]))
    globals()[f'{room_type[i]}_add'].grid(row=1, column=i)

root.mainloop()