I want to generate n amount of Tkinter buttons which do different things. I have this code:
import Tkinter as tk
for i in range(boardWidth):
newButton = tk.Button(root, text=str(i+1),
command=lambda: Board.playColumn(i+1, Board.getCurrentPlayer()))
Board.boardButtons.append(newButton)
If boardWidth is 5, though I get buttons labelled 1-5, when clicked they all do Board.playColumn(5, Board.getCurrentPlayer()).
I need the first button to do Board.playColumn(1, Board.getCurrentPlayer()), the second to do Board.playColumn(2, Board.getCurrentPlayer()) and so on.
Thanks for any help!
I think the problem is that the
lambda
is picking up the final value ofi
after thefor
loop ends. This should fix that (untested):Update
BTW, this worked by adding an argument to the
lambda
function with a default value calculated from the value ofi
at the time each one is created in the loop rather than referring back to the final value ofi
through a closure when the expression within it executes later.Your problem is that you create lots of
lambda
objects in the same namespace, and thoselambda
s make reference to names in the outer scope. That means they don't become closures and they don't store references to the objects until later... When it happens, all lambdas will refer to the last value ofi
.Try using a callback factory to fix that:
Another idea is to store the current value of i as a default argument value in the
lambda
object, instead of relying on closure behavior to store the reference: