动态分配按钮回调 - Python

时间:2017-12-09 00:13:20

标签: python-2.7

所以我最近开始使用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,无论什么按钮。有没有办法可以动态设置回调参数?

感谢您的帮助   - 雅各布

1 个答案:

答案 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)作为回调传递。