0

I have a grid of 9 buttons, which I've placed in a list of button objects, and I want the code that they execute in one method:

def click(which):
    print ("You clicked", which)
    # do stuff here

This code works but seem really inelegant:

b.append( Button(master, command=lambda: click(0) ) )
b.append( Button(master, command=lambda: click(1) ) )
b.append( Button(master, command=lambda: click(2) ) )
b.append( Button(master, command=lambda: click(3) ) )
b.append( Button(master, command=lambda: click(4) ) )
b.append( Button(master, command=lambda: click(5) ) )
b.append( Button(master, command=lambda: click(6) ) )
b.append( Button(master, command=lambda: click(7) ) )
b.append( Button(master, command=lambda: click(8) ) )

I really want something like this to work:

for i in range (0, 9):
    b.append( Button(master, command=lambda: click(i) ) )

But then "click(i)" is the command given to all the buttons, so every button click works with the current value of i in the code, not the value of i when the button was created. So I tried this instead:

for i in range (0, 9):
    callstring = "click(" + str(i) +")"
    b.append( Button(master, command=lambda: eval(callstring) ) )

But now all 9 of my button objects have "click(8)" as their command, and I can't for the life of me see why. Any help would be much appreciated.

  • 1
    This is covered in the Python FAQ under [Why do lambdas defined in a loop with different values all return the same result?](https://docs.python.org/3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result) (both the explanation and the usual workaround). It's also a frequent dup on StackOverflow; I'll find one with a good answer and mark it so you can find that. – abarnert Nov 06 '14 at 01:20
  • Actually, this one seems to have a "canonical" question, so I closed it to that… although really, I don't think it has the best answers. You can find other answers in some of the Linked questions. – abarnert Nov 06 '14 at 01:22

0 Answers0