所以我最近开始使用Python,我喜欢它。我想在我的第一个项目中创建一个计算器,我决定用循环添加按钮。但是按钮的回调始终是变量的最后一个状态,我想将其作为回调函数的参数传递。这是我的代码。
def addButtons():
buttons = []
label = ""
num = 0
posX = 4
posY = 1
for i in range(12):
if (i % 4 < 3):
num += 1
label = str(num)
else:
label = "Blank"
if (i % 4 == 0):
posY += 1
if (posX < 3):
posX += 1
else:
posX = 0
buttons.append(
Button(buttonPanel, text=label, command=lambda: function(i), relief="flat", borderwidth=0, sticky=w, background="#fff", activebackground="#eee"))
buttons[i].grid(column=posX, row=posY, sticky=N + S + E + W)
buttonPanel.grid_columnconfigure(posX, weight=1)
buttonPanel.grid_rowconfigure(posY, weight=1)
functions.append(label)
def function(obj): # the button's functions are identified by this function and executed respectively
print obj
所以,当我点击一个按钮时,我总是从控制台得到11,无论什么按钮。有没有办法可以动态设置回调参数?
感谢您的帮助 - 雅各布
答案 0 :(得分:0)
您遇到的问题是,当您编写lambda: function(i)
时,lambda函数不会保存i
的当前值。相反,它只在被调用时在外部命名空间中查找它。这就是你在所有回调中看到i
的最后一个值的原因,因为那是上次修改时的值。
您可以通过将名称i
绑定到lambda中的特定值来避免此问题:
lambda i=i: function(i)
这有点滥用默认参数,但它完全符合您的要求。外部名称空间中i
的当前值被绑定为lambda函数名称空间中不同i
变量的默认值。当定义了lambda时会发生这种情况,因此外部名称空间的i
稍后会更改值并不重要。
另一种基本相同的方法是使用标准库的partial
模块中定义的functools
类型。它允许您将一些参数绑定到稍后可以调用的函数。这在以后期望一些其他参数时非常有用,但在这种情况下它也会有所帮助。而不是lambda,你将partial(function, i)
作为回调传递。