【问题标题】:How do you use the same function as the command for multiple buttons created in a loop?您如何使用与在循环中创建的多个按钮的命令相同的功能?
【发布时间】:2015-12-02 04:40:28
【问题描述】:

我正在创建一个井字游戏按钮板。单击每个按钮时,应交替切换为 X 或 O。我已经在 for 循环中创建了按钮,如果可能的话,我希望避免单独初始化它们。 我尝试使用 lambda 将按钮传递给函数,并尝试通过调用按钮 self.bttn 来消除命令中的参数问题(因为这一切都发生在我修改后的 Frame 类中)。然而,在这两种情况下,我都遇到了这样一个问题,即无论我点击 9 个按钮中的哪一个,由 for 循环创建的最终按钮都会响应。

def __build_board(self):
    """ Creates tic-tac-toe board of 9 blank buttons. """
    for row_num in range(3):
        for col_num in range(3):
            self.bttn = Button(self, text = "    ", command = self.__change_button)
            self.bttn.grid(row = row_num + 1, column = col_num, sticky = W)

这就是我尝试使用 self.bttn 的方式。 self.__change_button 只是将 self.bttn 中的文本切换为 X 或 O。 这就是我尝试使用 lambda 的方式...

def __build_board(self):
    """ Creates tic-tac-toe board of 9 blank buttons. """
    for row_num in range(3):
        for col_num in range(3):
            bttn = Button(self, text = "    ", command = lambda: self.__change_button(bttn))
            bttn.grid(row = row_num + 1, column = col_num, sticky = W)

我想我明白为什么这些方法行不通了。看起来,我已经命令所有按钮更改最后一个按钮的文本,但我不知道如何让它们按照我想要的方式更改自己的文本。任何帮助将不胜感激。

【问题讨论】:

    标签: python


    【解决方案1】:

    这是一个棘手的问题...

    原因是 lambda 将绑定到 bttn 变量,而不是绑定到它的值,因此所有按钮都将作用于最后一个按钮(因为那将是值循环后的变量)。

    要看到这一点,请考虑:

    x = 1
    y = lambda : x
    print(y()) # will print 1
    x = 2
    print(y()) # will print 2; lambda captures variables, not values
    

    一种可能的解决方法是:

    def __build_board(self):
        """ Creates tic-tac-toe board of 9 blank buttons. """
        for row_num in range(3):
            for col_num in range(3):
                def mkbutton():
                    b = Button(self, text = "    ",
                               command = lambda: self.__change_button(b))
                    return b
                bttn = mkbutton()
                bttn.grid(row = row_num + 1, column = col_num, sticky = W)
    

    这样每个lambda 都将绑定到它自己的独立变量b。

    通常这种问题可以用频繁模式更容易解决:

    x = lambda y=y: ...
    

    其中 y 的值被复制为 lambda 的可选参数的默认值。

    但是,在您的情况下,这种方法是不可能的,因为在评估 lambda 时,Button 实例还不存在(因此您不能将其作为默认参数值存储在 lambda 本身中)。

    【讨论】:

    • 非常感谢!我会尝试这个解决方案,虽然关于 lambda 的很多讨论都让我头疼(我今天早些时候才第一次遇到它,这是我最初寻找这个问题的解决方案时第一次遇到),但我希望我会在未来。再次感谢您!
    猜你喜欢
    • 2018-06-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多