1

I am using python 3 with tkinter and I am having issues with a command I want to execute from a button. A variable number of buttons are generated, one for each visitor, and I am trying to call the function signOut from the button press whilst passing the relevent item (visitor) from the list to it.

I realise that the issue is with the for loop as by the time the button is pressed, i will == the last item in the list. How can I make it specific to the actual visitor. I can't seem to think of the solution. Any advice is appreciated.

buttonDictionary = {}
for i in range(0,len(currentVisitors)):
    buttonDictionary[i] = Button(bottomFrame, text=currentVisitors[i], command=lambda: signOut(topFrame, bottomFrame, currentVisitors[i]))
    buttonDictionary[i].pack()
0

1 Answer 1

2

It is my understanding that e.g. i in a lambda within a loop like this is referring to the variable i itself, not the value of the variable on each iteration, so that when the command callback is called, it will use the value of i at that moment, which as you noticed is the value on the last iteration.

One way to solve this is with a partial. partial will, in effect "freeze" the arguments at their current state in the loop and use those when calling the callback.

Try using a partial instead of a lambda like this:

from functools import partial

buttonDictionary = {}
for i in range(0,len(currentVisitors)):
    buttonDictionary[i] = Button(bottomFrame, text=currentVisitors[i], command=partial(signOut, topFrame, bottomFrame, currentVisitors[i]))
    buttonDictionary[i].pack()

Another way I have seen this done, but haven't tried, is to assign i to a new variable in your lambda each time:

command=lambda i=i: signOut(topFrame, bottomFrame, currentVisitors[i])

I have gotten burned bad more than once when I first started with Python by using lambdas in loops (including a case very similar to this trying to assign a callback to dynamically generated buttons in a loop). I even created a snippet that would expand to think_about_it('are you sure you want to use a lambda?') whenever I typed lambda just to remind me of the pain I caused myself with that...

Sign up to request clarification or add additional context in comments.

2 Comments

That did indeed solve the problem. Thanks a lot for your reply!
@user3931640 Glad it worked! I have been burned by this a few times. The worst thing is when you don't notice it is happening. I will try to update my answer a little bit with an explanation as to why this happens, or at least link to someone who can explain it well.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.