3

I have this code to create a series of bindings in a loop:

from Tkinter import *
keys = {0:'m', 1:'n', 2:'o'}
def SomeFunc(event=None,number=11):
    print keys[number], number
root = Tk()
field = Canvas(root, height = 200, width = 200, bg = "gray") 
for i in range(2):
    root.bind("<KeyPress-%c>" % keys[i],lambda ev:SomeFunc(ev,i))
field.pack()
root.mainloop()

my problem is that when I press 'm' or 'n' the function SomeFunc gets called with the vairable 'i' as an argument. I would like it to be called with a 0 as argument (the numerical value 'i' had when 'bind' was used) when I press 'm' and with 1 when I press 'n'. Can this be done?

sloth
  • 99,095
  • 21
  • 171
  • 219
user1966118
  • 31
  • 1
  • 2

1 Answers1

7

Your problem here is that the variable i gets captured by the lambda, but you can get around that by creating a little helper function for example:

for i in range(2):
    def make_lambda(x):
        return lambda ev:SomeFunc(ev,x)
    root.bind("<KeyPress-%c>" % keys[i], make_lambda(i))

This creates a new scope for each binding you create, thus executing the for loop and changing of i during the loop does not influence your already lambda functions.

sloth
  • 99,095
  • 21
  • 171
  • 219