为什么我的计算器程序不起作用 - Python?

时间:2014-06-22 20:09:26

标签: python user-interface python-3.x tkinter calculator

我正在为计算器编写程序,但我遇到了一个小问题。 每当我按下其中一个按钮时,它每次都会增加9,即使它应该是i(来自for循环)。 请有人告诉我为什么它总是9岁吗?

代码 -

import tkinter

plus = True

numbers = 0

def main():

    def numButton(i):
        global numbers
        if plus == False:
            numbers-=i
        else:
            numbers+=i
    def quitHandler():
        root.destroy()
    def entryHandler():
        global numbers
        numbers+=int(text.get())
        text.set("")
    def printHandler():
        text2.set(numbers)
    def restartHandler():
        global numbers
        root.destroy()
        plus = True
        numbers = 0
        main()
    def plusHandler():
        global plus
        plus = True
    def minusHandler():
        global plus
        plus = False

    root = tkinter.Tk()
    frame = tkinter.Frame(root).pack(side=tkinter.TOP)

    text = tkinter.IntVar()
    text2 = tkinter.IntVar()
    text.set("")
    text2.set("")

    tkinter.Entry(frame,bd =8,textvariable=text).pack()

    tkinter.Button(frame,padx=8,pady=8,bd=8,text="Enter",command=entryHandler).pack()
    tkinter.Button(frame,padx=8,pady=8,bd=8,text="Quit",command=quitHandler).pack(side=tkinter.RIGHT)
    tkinter.Button(frame,padx=8,pady=8,bd=8,text="Restart",command=restartHandler).pack(side=tkinter.RIGHT)
    tkinter.Button(frame,padx=8,pady=8,bd=8,text="Print",command=printHandler).pack(side=tkinter.LEFT)

    tkinter.Entry(frame,bd =8,textvariable=text2).pack(side=tkinter.LEFT)

    _padx = 16
    _pady = 16
    _bd = 8

    for i in range (1,10):
        tkinter.Button(frame, padx = _padx, pady = _pady, bd = _bd, text = str(i), command = lambda: numButton(i)).pack(side = tkinter.LEFT)

    tkinter.Button(frame,padx=8,pady=8,bd=8,text="+",command=plusHandler).pack(side=tkinter.LEFT)
    tkinter.Button(frame,padx=8,pady=8,bd=8,text="-",command=minusHandler).pack(side=tkinter.LEFT)

main()

有人还可以告诉我如何将所有内容放在此网站上的代码内容中,我无法弄明白,网站帮助显示我的方式无效(或请管理员修复)。


好的,谢谢你们,有人通过电子邮件向我发送了解决方案:

    tkinter.Button(frame, padx = _padx, pady = _pady, bd = _bd, text = str(i), command = lambda i=i: numButton(i)).pack(side = tkinter.LEFT)

必须在lamda之后添加i = i。 有人可以向我解释一下i = i的事情吗?

由于

2 个答案:

答案 0 :(得分:1)

command = lambda: numButton(i)

这不会在lambda创建时查找i的值并将其插入到函数中。当调用lambda时,然后它会查找i。到那时i总是9

有几种方法可以解决这个问题,所有这些方法都集中在确保在i的创建时间而不是执行时间查找command。我使用的是functools.partial,一个用于将函数与参数相关联的工具:

from functools import partial
...
command=partial(numButton, i)

你也可以使用默认参数,这是一种kludgy:

command=lambda i=i: numButton(i)

或者写一个工厂功能:

def closure_maker(i):
    def closure():
        numButton(i)
    return closure
...
command=closure_maker(i)

答案 1 :(得分:0)

用于命令的lambda函数引用变量i

for i in range (1,10):
    tkinter.Button(frame, padx = _padx, pady = _pady, bd = _bd, text = str(i),
            command = lambda: numButton(i)).pack(side = tkinter.LEFT)

执行命令并运行lambda函数时,它会选择按钮编号i。但是那时,当执行lambda函数时,i包含值9i循环之后的值for结束了创建按钮完成。

要解决此问题,请确保lambda函数不会共享同一个全局变量。一种方法是使用创建新局部范围的函数:

def numCommand(x):
    return (lambda: numButton(x))

for i in range (1,10):
    tkinter.Button(frame, padx = _padx, pady = _pady, bd = _bd, text = str(i),
            command = numCommand(i)).pack(side = tkinter.LEFT)

此处每个lambda函数都引用其x调用中自己的numCommand()变量。