Search code examples
pythontkinterbuttonglobal-variables

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


Using tkinter and python to build a GUI and I'm adding buttons using globals() based off a list of room_types. However, the variable I'm passing into the button's command is always the last item on the list, even though every other instance of using room_type[i] correlates to the correct element.

This is what I'm having problems with.

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

It makes 7 buttons, each with text that indicates the different room types, but for some reason, r always equals the last element in the list. In this case, dining_room.


Solution

  • Capture the current value of i when declaring the 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=lambda pi=i: new_room(r=room_type[pi]))
        globals()[f'{room_type[i]}_add'].grid(row=1, column=i)
    
    root.mainloop()