tkinter在for循环传递命令参数中创建按钮

Mar*_*cel 26 python tkinter button

我试图在for循环中创建tkinter中的按钮.并且每个循环都将i count值作为参数传递给命令值.因此,当从命令值调用函数时,我可以判断按下了哪个按钮并相应地执行操作.问题是,假设len为3,它将创建3个按钮,标题为"Game 1"到"Game 3",但是当按下任何按钮时,打印值总是2,即最后一次迭代.因此看起来按钮是作为单独的实体制作的,但命令参数中的i值似乎完全相同.这是代码:

def createGameURLs(self):
    self.button = []
    for i in range(3):
        self.button.append(Button(self, text='Game '+str(i+1),command=lambda:self.open_this(i)))
        self.button[i].grid(column=4, row=i+1, sticky=W)
def open_this(self, myNum):
    print(myNum)
Run Code Online (Sandbox Code Playgroud)

有没有办法在每次迭代时获得当前的i值以坚持使用该特定按钮?

Bre*_*arn 59

将你的lambda改为lambda i=i: self.open_this(i).

这可能看起来很神奇,但这就是正在发生的事情.当您使用该lambda定义函数时,open_this调用在您定义函数时不会获取变量i的值.相反,它会产生一个闭包,这有点像对自己的说法,"我应该在我被称为时,寻找变量i的值." 当然,在循环结束后调用该函数,所以此时我将始终等于循环中的最后一个值.

使用该i=i技巧会导致函数在定义lambda时存储i的当前值,而不是等待稍后查找i的值.

  • 这是一个精彩、简单、很好的解释。这应该是答案。 (4认同)
  • @Amen:这取决于你想要的那些论点.如果两者都来自某个外部循环并且你想以上面显示的方式"冻结"它们,那么你只需要`lambda x = x,y = y:self.open_this(x,y)`. (3认同)
  • 如果我们想将两个参数传递给像 open_this 这样的函数怎么办? (2认同)

luk*_*kad 6

这就是闭包在python中的工作方式.我曾经遇到过这个问题.你可以用functools.partial它.

for i in range(3):
    self.button.append(Button(self, text='Game '+str(i+1), command=partial(self.open_this, i)))
Run Code Online (Sandbox Code Playgroud)

  • @Lucem“如果您使用虚拟环境,您可能会遇到问题”没有充分的理由,因为 `functools.partial` 是标准库的一部分并且已经存在很长时间了。如果您遇到困难,那么您应该尝试诊断问题并提出自己的问题。 (2认同)