Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用与循环中创建的多个按钮的命令相同的功能?_Python - Fatal编程技术网

Python 如何使用与循环中创建的多个按钮的命令相同的功能?

Python 如何使用与循环中创建的多个按钮的命令相同的功能?,python,Python,我正在创建一个由按钮组成的tic-tac趾板。单击每个按钮时,应交替切换到X或O。我在里面为循环创建了按钮,如果可能的话,我希望避免单独初始化它们。 我尝试使用lambda将按钮传递给函数,并尝试通过调用buttons self.bttn来消除命令中的参数问题(因为这都发生在我修改过的Frame类中)。然而,在这两种情况下,我都遇到了一个问题,即无论我单击9个按钮中的哪一个,for循环创建的最后一个按钮都会响应 def __build_board(self): """ Creates t

我正在创建一个由按钮组成的tic-tac趾板。单击每个按钮时,应交替切换到X或O。我在里面为循环创建了按钮,如果可能的话,我希望避免单独初始化它们。 我尝试使用lambda将按钮传递给函数,并尝试通过调用buttons 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.\u change\u按钮仅将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)

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

这是一个棘手的问题

原因是
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
时,
按钮
实例还不存在(因此您不能将其作为默认参数值存储在lambda本身中)。

这是一个棘手的问题

原因是
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
时,
按钮
实例还不存在(因此您不能将其作为默认参数值存储在lambda本身中)。

非常感谢!我将尝试这个解决方案,尽管关于lambda的讨论很多都超出了我的想象(今天早些时候,在我最初寻找这个问题的解决方案时,我才第一次遇到它),但我希望我将来会了解更多。再次感谢你!非常感谢你!我将尝试这个解决方案,尽管关于lambda的讨论很多都超出了我的想象(今天早些时候,在我最初寻找这个问题的解决方案时,我才第一次遇到它),但我希望我将来会了解更多。再次感谢你!