我正在使用python制作计算器,它在计算带括号的表达式时显示错误

时间:2018-05-01 11:23:19

标签: python tkinter calculator

在使用括号like->计算表达式时显示此错误86 * 4(3 + 5)88:

TypeError:'int'对象不可调用

当我不使用计算器按钮并使用我的键盘按钮键入时,它不显示任何错误,但按下等于它会给出错误答案。

请检查我的代码并指出错误。

from tkinter import *

cal = Tk()
cal.title("Smart Calculator")

txtDisplay = Entry(cal, font=('arial', 20, 'bold'), bd=30, insertwidth=4, 
bg="powder blue", justify='right')

class Calculator:

    def __init__(self):
        self.result = 0
        self.current = 0
        self.operator = ""

    def btnClick(self, num):
            self.operator = self.operator + str(num)
            txtDisplay.delete(0, END)
            txtDisplay.insert(0, self.operator)
            self.expOutput(self.operator)

    def expOutput(self, operator):
        try:
            self.result = str(eval(operator))
            txtDisplay.delete(0, END)
            txtDisplay.insert(0, string=self.operator + "=" + self.result)
            self.current = 0
        except SyntaxError:
            txtDisplay.delete(0, END)
            txtDisplay.insert(0, self.operator)

    def oprtrClick(self, op):
        if self.current is 0:
            self.current = 1
            self.operator = self.operator + op
            txtDisplay.delete(0, END)
            txtDisplay.insert(0, string=self.operator)
        else:
            self.operator = self.operator + op
            self.expOutput(self.operator)

    def equals(self):
        self.operator = self.result
        txtDisplay.delete(0, END)
        txtDisplay.insert(0, string=self.operator)

    def clear(self):
        self.__init__()
        txtDisplay.delete(0, END)

    def delete(self):
        self.operator = self.operator[: -1]
        txtDisplay.delete(0, END)
        txtDisplay.insert(0, string=self.operator)

smartCal = Calculator()

btn0 = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 
'bold'), text="0",bg="powder blue", command=lambda: smartCal.btnClick(0))


btn1 = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 
'bold'), text="1",
          bg="powder blue", command=lambda: smartCal.btnClick(1))

btn2 = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 
'bold'), text="2",bg="powder blue", command=lambda: smartCal.btnClick(2))


btn3 = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 
'bold'), text="3",
          bg="powder blue", command=lambda: smartCal.btnClick(3))

btn4 = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="4",
          bg="powder blue", command=lambda: smartCal.btnClick(4))

btn5 = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="5",
          bg="powder blue", command=lambda: smartCal.btnClick(5))

btn6 = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="6",
          bg="powder blue", command=lambda: smartCal.btnClick(6))

btn7 = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="7",
          bg="powder blue", command=lambda: smartCal.btnClick(7))

btn8 = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="8",
          bg="powder blue", command=lambda: smartCal.btnClick(8))

btn9 = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="9",
          bg="powder blue", command=lambda: smartCal.btnClick(9))

btnDecimal = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text=".",
               bg="powder blue", command=lambda: smartCal.btnClick("."))

btnLeftParen = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="(",
               bg="powder blue", command=lambda: smartCal.btnClick("("))

btnRightParen = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text=")",
               bg="powder blue", command=lambda: smartCal.btnClick(")"))

Add_btn = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="+",
             bg="powder blue", command=lambda: smartCal.oprtrClick("+"))

Sub_btn = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="-",
             bg="powder blue", command=lambda: smartCal.oprtrClick("-"))

Mul_btn = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="*",
             bg="powder blue", command=lambda: smartCal.oprtrClick("*"))

Div_btn = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="/",
             bg="powder blue", command=lambda: smartCal.oprtrClick("/"))

btnEquals = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="=",
               bg="powder blue", command=smartCal.equals)

btnClear = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="C",
              bg="powder blue", command=smartCal.clear)

btnBackspace = Button(cal, padx=16, pady=16, bd=8, fg="black", font=('arial', 20, 'bold'), text="⌫",
              bg="powder blue", command=smartCal.delete)

# ~*~*~Positioning~*~*~

txtDisplay.grid(columnspan=4)
# =========ROW1================== #
btn7.grid(row=1, column=0)
btn8.grid(row=1, column=1)
btn9.grid(row=1, column=2)
Add_btn.grid(row=1, column=3)
# =========ROW2================== #
btn4.grid(row=2, column=0)
btn5.grid(row=2, column=1)
btn6.grid(row=2, column=2)
Sub_btn.grid(row=2, column=3)
# =========ROW3================== #
btn1.grid(row=3, column=0)
btn2.grid(row=3, column=1)
btn3.grid(row=3, column=2)
Mul_btn.grid(row=3, column=3)
# =========ROW4================== #
btn0.grid(row=4, column=0)
btnClear.grid(row=4, column=1)
btnEquals.grid(row=4, column=2)
Div_btn.grid(row=4, column=3)
# =========ROW5================== #
btnDecimal.grid(row=5, column=0)
btnLeftParen.grid(row=5, column=1)
btnRightParen.grid(row=5, column=2)
btnBackspace.grid(row=5, column=3)

cal.mainloop()

2 个答案:

答案 0 :(得分:1)

在您的方法expOutput中,您应该在开始或结束括号前后的*字符串中添加缺少的operator符号。

这需要在调用eval(operator)之前通过调用解析函数来完成,比如add_missing_mult

解析函数的简单实现可能如下所示:

def add_missing_mult(s):

    splitted = s.split('(')
    for i, sub in enumerate(splitted[:-1]):
        if sub[-1].isdigit() or sub[-1] == '.':
            splitted[i] += "*"
    s = '('.join(splitted)

    splitted = s.split(')')
    for i, sub in enumerate(splitted[1:]):
        if sub[0].isdigit():
            splitted[i+1] = "*" + splitted[i+1]
    return ')'.join(splitted)

add_missing_mult('86*4(3+5)88')

>>>'86*4*(3+5)*88'

然后在expOutput

operator = add_missing_mult(operator)
try:
    self.result = str(eval(operator))
    txtDisplay.delete(0, END)
    ...

但是在一个真实的项目中,你会看到使用像this question

这样的正则表达式

答案 1 :(得分:1)

我在不使用解析功能的情况下解决了问题。我使用了两个新变量 - isButton和isRightParen以及两个新函数 - leftParenthesesClick()和rightParenthesesClick()。 isButton会跟踪最后一个按下的按钮是否为数字(0-9)。当用户按下左括号时,首先它检查isRightParen是否为1然后它在左括号前包含*符号,然后如果isButton为1则还包括*,否则左括号将按原样打印。

请检查我的代码并告诉我这种方式是否正常,是否存在错误,或者有更好更短的方法来执行此操作。 @Jacques Gaudin @PM 2Ring 我稍后会尝试使用解析函数以及建议。 :)

def __init__(self):
    self.var1 = ""
    self.var2 = ""
    self.output = 0
    self.current = 0
    self.operator = ""
    self.isButton = 0
    self.isRightParen = 0

def btnClick(self, num):
    if self.isRightParen is 1:
        self.operator = self.operator + "*" + str(num)
        txtDisplay.delete(0, END)
        txtDisplay.insert(0, self.operator)
        self.expOutput(self.operator)
        self.isButton = 1
        self.isRightParen = 0

    elif self.isRightParen is 0:
        self.operator = self.operator + str(num)
        txtDisplay.delete(0, END)
        txtDisplay.insert(0, self.operator)
        self.expOutput(self.operator)
        self.isButton = 1
        self.isRightParen = 0

def leftParenthesesClick(self):

    if self.isRightParen is 1:
        self.operator = self.operator + "*" + "("
        txtDisplay.delete(0, END)
        txtDisplay.insert(0, self.operator)
        self.isRightParen = 0

    elif self.isButton is 0:
        self.operator = self.operator + "("
        txtDisplay.delete(0, END)
        txtDisplay.insert(0, self.operator)
        self.isRightParen = 0
    elif self.isButton is 1:
        self.operator = self.operator + "*" + "("
        txtDisplay.delete(0, END)
        txtDisplay.insert(0, self.operator)
        self.isRightParen = 0

def rightParenthesesClick(self):
    self.operator = self.operator + ")"
    txtDisplay.delete(0, END)
    txtDisplay.insert(0, self.operator)
    self.expOutput(self.operator)
    self.isRightParen = 1

def expOutput(self, operator):
    try:
        self.output = str(eval(operator))
        txtDisplay.delete(0, END)
        txtDisplay.insert(0, string=self.operator + "=" + self.output)
        self.current = 0
    except SyntaxError:
        txtDisplay.delete(0, END)
        txtDisplay.insert(0, self.operator)


def oprtrClick(self, op):
    if self.current is 0:
        self.current = 1
        self.operator = self.operator + op
        txtDisplay.delete(0, END)
        txtDisplay.insert(0, string=self.operator)
        self.isButton = 0
        self.isRightParen = 0
    else:
        self.operator = self.operator + op
        self.isButton = 0
        self.isRightParen = 0
        self.expOutput(self.operator)