11

first of all, sorry for the title, I couldn't find a better one.

The following code is a minimalized version of a problem I have in my Python program (I am a newbie btw.).

def onClick(i):
    print "This is Button: " + str(i)
    return

def start():
    b = [0 for x in range(5)]
    win = Tkinter.Tk()
    for i in range(5):
        b[i] = Tkinter.Button(win,height=10,width=100,command=lambda : onClick(i))
        b[i].pack()
    return

What it does: Whatever Button I click, it says "This is Button: 4".

What I want: First button should say "This is Button: 0" and so on.

Is this a wanted behaviour of Python? And if the answer is yes, why is that so? How can I fix it?

On the other hand, this works fine:

def start():        
    x = [0 for x in range(5)]
    for i in range(5):
        x[i] = lambda:onClick(i)
        x[i]()
    return
kaan
  • 796
  • 2
  • 6
  • 20

1 Answers1

13

Use default parameter to avoid late-binding issue (Otherwise i is bound when the lambda function is called, not when it is created):

def start():
    buttons = []
    win = Tkinter.Tk()
    for i in range(5):
        b = Tkinter.Button(win, height=10, width=100, command=lambda i=i: onClick(i))
        b.pack()
        buttons.append(b)
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • And how can I use `i` inside the `onClick()` for example to change the `buttons[i]` color ? – ioaniatr May 22 '18 at 17:42
  • Found it. With `buttons[i]` is the reference of the object, so, you only use `buttons[i].config(fg = "red")` to do that. Great answer. Thanks. – ioaniatr May 22 '18 at 19:36