python不同的lambda函数返回相同的结果
我目前正在尝试用Python为Tic-Tac-Toe编写GUI。为此,我正在使用tkinter。我想为每个位置创建一个按钮,以便通过单击其中一个按钮进行移动。现在的问题是,我希望根据单击的按钮调用具有不同参数的函数。因此,我尝试使用lambda表达式,但无论单击哪个按钮,结果都是相同的调用python不同的lambda函数返回相同的结果,python,function,tkinter,lambda,Python,Function,Tkinter,Lambda,我目前正在尝试用Python为Tic-Tac-Toe编写GUI。为此,我正在使用tkinter。我想为每个位置创建一个按钮,以便通过单击其中一个按钮进行移动。现在的问题是,我希望根据单击的按钮调用具有不同参数的函数。因此,我尝试使用lambda表达式,但无论单击哪个按钮,结果都是相同的调用 import tkinter as tk class GameWindow: def __init__(self): win = tk.Tk() buttons
import tkinter as tk
class GameWindow:
def __init__(self):
win = tk.Tk()
buttons = [[tk.Button(win,text=str(i)+str(j)) for j in range(3)] for i in range(3)]
for i in range(3):
for j in range(3):
buttons[i][j]["command"] = lambda: print([i,j])
buttons[i][j].grid(row=i, column=j)
print([i,j])
win.mainloop()
test = GameWindow()
在这种情况下,我只想打印位置,但无论我单击哪个按钮,[2,2]都会被打印。您看到的问题是由于您创建了一个闭包。这意味着创建
lambda
的堆栈帧保持活动状态,并且lambda
指的是这些变量的当前值,而不是创建时的值。通过执行以下操作,您可以捕获它们的值:
def make_lambda(i, j):
return lambda: print([i, j])
然后在代码中替换:
buttons[i][j]["command"] = lambda: print([i,j])
与:
这将捕获并保留调用
make_lambda
时的值。这将是一个闭包,但它的框架将退出,它返回的lambda将是它唯一剩下的引用。可能lambda:print([str(i),str(j)])
,或者某种类型的类型转换将阻止这种情况发生。print([i,j])
行也将打印[2,2]
?还有一个更简单的解决方案,即使用参数默认值将lambda绑定到当前值,即按钮[i][j][“命令”]=lambda i=i,j=j:print([i,j])
@brunodesshuilliers,尽管它向lambda添加了两个可选参数,但仍然有效。如果您希望在向其传递任何参数时获得错误,这将阻止错误并覆盖这些值。在某些情况下,这可能足够了,但如果你想保留所需的参数,那么你需要像我所做的那样封装它。从技术上讲,你所说的是完全正确的。现在在实践中,在过去15年使用Python进行生产应用的过程中,这对我来说从来都不是一个问题。YMMV。。。
buttons[i][j]["command"] = make_lambda(i, j)