Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.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不同的lambda函数返回相同的结果_Python_Function_Tkinter_Lambda - Fatal编程技术网

python不同的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

我目前正在尝试用Python为Tic-Tac-Toe编写GUI。为此,我正在使用tkinter。我想为每个位置创建一个按钮,以便通过单击其中一个按钮进行移动。现在的问题是,我希望根据单击的按钮调用具有不同参数的函数。因此,我尝试使用lambda表达式,但无论单击哪个按钮,结果都是相同的调用

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)