In the world of programming, a calculator is a classic introductory project. It may seem simple, but it helps us grasp many core programming concepts, such as user input handling, conditional statements, loop structures, and function encapsulation. Today, we will implement a fully functional simple calculator using Python, starting from a basic command-line version to a graphical interface version, and even extending it to scientific calculation features.
Clear Goals: First, Look at the Final Effect
After running the program, users can input two numbers and an operator, and the program will return the calculation result. It supports addition, subtraction, multiplication, and division operations. If invalid characters are entered or an attempt is made to divide by zero, the program will provide a friendly error message. For the graphical version, users can complete input and calculations by clicking buttons, with a clean and intuitive interface.
Basic Version: Command-Line Calculator
Let’s start with the simplest command-line version. We will use the <span>input()</span>
function to get user input and the <span>eval()</span>
function to calculate the expression. Although <span>eval()</span>
has security issues, it is acceptable during the learning phase.
def simple_calculator():
print("Welcome to the simple calculator")
print("Supported operators: + (addition), - (subtraction), * (multiplication), / (division)")
print("Input 'q' to exit the program")
while True:
user_input = input("\nPlease enter an expression (e.g., 5 + 3):")
if user_input.lower() == 'q':
print("Thank you for using! Goodbye!")
break;
try:
result = eval(user_input)
print(f"Calculation result: {result}")
except ZeroDivisionError:
print("Error: The divisor cannot be zero!")
except:
print("Input error, please check if the expression is correct!")
if __name__ == "__main__":
simple_calculator()
After running this code, users can input expressions like <span>5 + 3</span>
, and the program will return <span>8</span>
. If the input is <span>10 / 0</span>
, it will prompt “The divisor cannot be zero”. Inputting <span>q</span>
will exit the program.
Advanced Version: Menu-Based Calculator
To make the program more user-friendly, we can design a menu interface that allows users to select the type of operation and then input two numbers separately.
def menu_calculator():
print("Welcome to the menu-based calculator")
print("1. Addition")
print("2. Subtraction")
print("3. Multiplication")
print("4. Division")
print("5. Exit")
while True:
choice = input("\nPlease select an operation (1-5):")
if choice == '5':
print("Thank you for using! Goodbye!")
break;
if choice not in ['1', '2', '3', '4']:
print("Invalid choice, please enter a number between 1-5!")
continue;
try:
num1 = float(input("Please enter the first number:"))
num2 = float(input("Please enter the second number:"))
except ValueError:
print("Input error, please enter a valid number!")
continue;
if choice == '1':
print(f"{num1} + {num2} = {num1 + num2}")
elif choice == '2':
print(f"{num1} - {num2} = {num1 - num2}")
elif choice == '3':
print(f"{num1} * {num2} = {num1 * num2}")
elif choice == '4':
if num2 == 0:
print("Error: The divisor cannot be zero!")
else:
print(f"{num1} / {num2} = {num1 / num2}")
if __name__ == "__main__":
menu_calculator()
This version guides users to select the type of operation through a menu, avoiding the complexity of directly inputting expressions, while also adding error handling mechanisms.
Graphical Version: Tkinter Calculator
To make the calculator more intuitive, we can use the Tkinter library to create a graphical interface. Users can input numbers and operators by clicking buttons, and click the “=” button to calculate the result.
import tkinter as tk
from tkinter import messagebox
class CalculatorGUI:
def __init__(self, root):
self.root = root
self.root.title("Graphical Calculator")
self.root.geometry("300x400")
self.root.resizable(False, False)
self.expression = ""
self.input_text = tk.StringVar()
self.create_widgets()
def create_widgets(self):
input_frame = tk.Frame(self.root, width=300, height=50, bd=0, highlightbackground="black", highlightcolor="black", highlightthickness=1)
input_frame.pack(side=tk.TOP)
input_field = tk.Entry(input_frame, font=('arial', 18, 'bold'), textvariable=self.input_text, width=50, bg="#eee", bd=0, justify=tk.RIGHT)
input_field.grid(row=0, column=0)
input_field.pack(ipady=10)
btn_frame = tk.Frame(self.root, width=300, height=350, bg="grey")
btn_frame.pack()
buttons = [
('7', 1, 0), ('8', 1, 1), ('9', 1, 2), ('/', 1, 3),
('4', 2, 0), ('5', 2, 1), ('6', 2, 2), ('*', 2, 3),
('1', 3, 0), ('2', 3, 1), ('3', 3, 2), ('-', 3, 3),
('0', 4, 0), ('.', 4, 1), ('=', 4, 2), ('+', 4, 3),
('C', 5, 0, 4)
]
for (text, row, col, colspan) in [x + (1,) if len(x) == 3 else x for x in buttons]:
if text == 'C':
btn = tk.Button(btn_frame, text=text, fg="black", width=10, height=3, bd=0, bg="#eee", cursor="hand2", command=self.clear)
btn.grid(row=row, column=col, columnspan=colspan, padx=1, pady=1)
elif text == '=':
btn = tk.Button(btn_frame, text=text, fg="black", width=10, height=3, bd=0, bg="#ddd", cursor="hand2", command=self.calculate)
btn.grid(row=row, column=col, padx=1, pady=1)
else:
btn = tk.Button(btn_frame, text=text, fg="black", width=10, height=3, bd=0, bg="#fff", cursor="hand2", command=lambda t=text: self.append(t))
btn.grid(row=row, column=col, padx=1, pady=1)
def append(self, value):
self.expression += str(value)
self.input_text.set(self.expression)
def clear(self):
self.expression = ""
self.input_text.set("")
def calculate(self):
try:
result = str(eval(self.expression))
self.input_text.set(result)
self.expression = result
except ZeroDivisionError:
messagebox.showerror("Error", "The divisor cannot be zero!")
self.clear()
except:
messagebox.showerror("Error", "Invalid expression!")
self.clear()
if __name__ == "__main__":
root = tk.Tk()
app = CalculatorGUI(root)
root.mainloop()
After running this code, a graphical calculator window will pop up. Users can input expressions by clicking number and operator buttons, click the “=” button to calculate the result, and click the “C” button to clear the input.
Extended Features: History and Scientific Calculations
To make the calculator more practical, we can add a history feature to record the user’s calculation process. Additionally, we can extend scientific calculation features to support square, square root, trigonometric functions, etc.
import tkinter as tk
from tkinter import messagebox, Listbox, Scrollbar
import math
class AdvancedCalculatorGUI:
def __init__(self, root):
self.root = root
self.root.title("Advanced Calculator")
self.root.geometry("400x500")
self.root.resizable(False, False)
self.expression = ""
self.input_text = tk.StringVar()
self.history = []
self.create_widgets()
def create_widgets(self):
# Input box
input_frame = tk.Frame(self.root, width=400, height=50, bd=0, highlightbackground="black", highlightcolor="black", highlightthickness=1)
input_frame.pack(side=tk.TOP)
input_field = tk.Entry(input_frame, font=('arial', 18, 'bold'), textvariable=self.input_text, width=50, bg="#eee", bd=0, justify=tk.RIGHT)
input_field.grid(row=0, column=0)
input_field.pack(ipady=10)
# Button area
btn_frame = tk.Frame(self.root, width=400, height=400, bg="grey")
btn_frame.pack()
# Basic operation buttons
buttons = [
('7', 1, 0), ('8', 1, 1), ('9', 1, 2), ('/', 1, 3),
('4', 2, 0), ('5', 2, 1), ('6', 2, 2), ('*', 2, 3),
('1', 3, 0), ('2', 3, 1), ('3', 3, 2), ('-', 3, 3),
('0', 4, 0), ('.', 4, 1), ('=', 4, 2), ('+', 4, 3),
('C', 5, 0, 4)
]
for (text, row, col, colspan) in [x + (1,) if len(x) == 3 else x for x in buttons]:
if text == 'C':
btn = tk.Button(btn_frame, text=text, fg="black", width=10, height=3, bd=0, bg="#eee", cursor="hand2", command=self.clear)
btn.grid(row=row, column=col, columnspan=colspan, padx=1, pady=1)
elif text == '=':
btn = tk.Button(btn_frame, text=text, fg="black", width=10, height=3, bd=0, bg="#ddd", cursor="hand2", command=self.calculate)
btn.grid(row=row, column=col, padx=1, pady=1)
else:
btn = tk.Button(btn_frame, text=text, fg="black", width=10, height=3, bd=0, bg="#fff", cursor="hand2", command=lambda t=text: self.append(t))
btn.grid(row=row, column=col, padx=1, pady=1)
# Scientific calculation buttons
scientific_buttons = [
('sin', 0, 0), ('cos', 0, 1), ('tan', 0, 2),
('sqrt', 0, 3), ('^2', 0, 4)
]
for text, row, col in scientific_buttons:
btn = tk.Button(btn_frame, text=text, fg="black", width=10, height=3, bd=0, bg="#f8f8f8", cursor="hand2", command=lambda t=text: self.scientific_operation(t))
btn.grid(row=row, column=col, padx=1, pady=1)
# History area
history_frame = tk.Frame(self.root, width=400, height=100, bg="#f0f0f0")
history_frame.pack(side=tk.BOTTOM, fill=tk.X)
scrollbar = Scrollbar(history_frame)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.history_listbox = Listbox(history_frame, height=5, width=50, yscrollcommand=scrollbar.set)
self.history_listbox.pack(side=tk.LEFT, fill=tk.BOTH)
scrollbar.config(command=self.history_listbox.yview)
def append(self, value):
self.expression += str(value)
self.input_text.set(self.expression)
def clear(self):
self.expression = ""
self.input_text.set("")
def calculate(self):
try:
result = str(eval(self.expression))
self.input_text.set(result)
self.history.append(f"{self.expression} = {result}")
self.update_history()
self.expression = result
except ZeroDivisionError:
messagebox.showerror("Error", "The divisor cannot be zero!")
self.clear()
except:
messagebox.showerror("Error", "Invalid expression!")
self.clear()
def scientific_operation(self, operation):
try:
if not self.expression:
messagebox.showerror("Error", "Please enter a number before performing scientific operations!")
return;
num = float(self.expression)
if operation == 'sin':
result = math.sin(math.radians(num))
elif operation == 'cos':
result = math.cos(math.radians(num))
elif operation == 'tan':
result = math.tan(math.radians(num))
elif operation == 'sqrt':
if num < 0:
messagebox.showerror("Error", "Negative numbers cannot be square rooted!")
return;
result = math.sqrt(num)
elif operation == '^2':
result = num ** 2
self.input_text.set(str(result))
self.history.append(f"{operation}({num}) = {result}")
self.update_history()
self.expression = str(result)
except:
messagebox.showerror("Error", "Scientific operation failed!")
self.clear()
def update_history(self):
self.history_listbox.delete(0, tk.END)
for item in self.history[-5:]: # Only show the last 5 records
self.history_listbox.insert(tk.END, item)
if __name__ == "__main__":
root = tk.Tk()
app = AdvancedCalculatorGUI(root)
root.mainloop()
This version adds scientific calculation features, such as sine, cosine, tangent, square root, and square operations. Additionally, the history area at the bottom displays the most recent calculation records for easy user reference.
Conclusion: From Simple to Complex, Step by Step
By implementing these different versions of the calculator, we not only mastered the basic syntax of Python but also learned how to handle user input, design graphical interfaces, and extend functionalities. From the command-line version to the graphical version, and finally to the advanced version with history and scientific calculation features, each step deepens our understanding of programming.
If you are a beginner, you can start with the command-line version and gradually try more complex versions. If you already have some experience, you can attempt to extend more features, such as supporting more scientific calculations, adding unit conversion functions, or even packaging the calculator into an executable file for use on different devices.
The charm of programming lies in this: starting from a simple idea, through continuous practice and exploration, ultimately achieving a fully functional tool. This process is the best way for us to learn and grow.