Creation of the button array



  • There is a need to create a range of buttons and to define each action (change the button). However, only the last element in the matrix responds to the pressure.

    from tkinter import *
    

    def changeBut(event, button):
    #что-то сделать с кнопкой

    root = Tk()

    for i in range(10):
    for j in range(10):
    but = Button(root, borderwidth = 0)
    but["text"] = str(i) + "_" + str(j)
    but.bind("<Button-1>", lambda event: changeBut(event, but))
    but.grid(row = i, column = j)

    root.mainloop()



  • The problem is, in Python, the function is looking for the variable, not at the time of its creation, but at the time of the challenge.

    In your case, all functions created through lambda will receive the same meaning. but - last.

    In order not to do so, it is clearly necessary to link the necessary meaning by using the default argument:

    but.bind("<Button-1>", lambda event, but=but: changeBut(event, but))
    

    After that, your function will work as expected.


    The same problem can be demonstrated in a simpler example. Let us set up a list of functions that return squares between 0 and 4. Use the roster generator (or cycle, no matter):

    functions = [lambda: i * i for  i in range(5)]
    

    Now we have a list of five functions. Let's try to do it:

    for i in range(10):
        print(functions[i](), end=' ')
    

    16 16 16 16 16 instead of expected 0 1 4 9 16

    In order to obtain expected behaviour, the necessary value must be clearly transferred:

    functions = [lambda i=i: i * i for  i in range(5)]
    

    In order to figure out why this is happening, we need to know how the Python is looking. First, the variable is seen in the local area of the name, then in the area in which it is invested and so on to objects from the built-in area of the name.




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2