สร้างเครื่องคิดเลขพื้นฐานใน Python ที่รองรับ 4 ดำเนินการหลัก: บวก, ลบ, คูณ, หาร พร้อมจัดการ Error Handling และ User Input
Implementation แบบ Function-Based
def add(a, b):
"""บวก"""
return a + b
def subtract(a, b):
"""ลบ"""
return a - b
def multiply(a, b):
"""คูณ"""
return a * b
def divide(a, b):
"""หาร (จัดการหารศูนย์)"""
if b == 0:
raise ValueError("ไม่สามารถหารด้วยศูนย์ได้")
return a / b
def calculator():
"""Main Calculator Loop"""
operations = {
'+': add,
'-': subtract,
'*': multiply,
'/': divide,
}
print("=== Basic Calculator ===")
print("Operations: +, -, *, /")
print("Type 'quit' to exit\n")
while True:
try:
# Get Operator
op = input("Enter operator (+, -, *, /) or 'quit': ").strip()
if op.lower() == 'quit':
print("Goodbye!")
break
if op not in operations:
print("Invalid operator! Use +, -, *, /")
continue
# Get Operands
a = float(input("Enter first number: "))
b = float(input("Enter second number: "))
# Calculate
result = operations[op](a, b)
print(f"Result: {a} {op} {b} = {result}\n")
except ValueError as e:
print(f"Error: {e}\n")
except KeyboardInterrupt:
print("\nGoodbye!")
break
except Exception as e:
print(f"Unexpected error: {e}\n")
# Run
if __name__ == "__main__":
calculator()
Enhanced Version: Expression Evaluator
ใช้ eval() อย่างปลอดภัยกับ Allowlist (ดูรายละเอียดในบทความ eval())
import re
SAFE_FUNCTIONS = {
'abs': abs, 'round': round, 'min': min, 'max': max,
'sum': sum, 'pow': pow,
}
def safe_eval(expr):
"""Safe Evaluation for Math Expressions"""
# Validate: Only allow numbers, operators, parentheses, allowed functions
if not re.match(r'^[0-9+\-*/().,\s]+$', expr.replace(' ', '')):
# Check for function calls
func_calls = re.findall(r'([a-zA-Z_][a-zA-Z0-9_]*)\s*\(', expr)
for func in func_calls:
if func not in SAFE_FUNCTIONS:
raise ValueError(f"Function '{func}' not allowed")
# Execute with Restricted Globals
return eval(expr, {"__builtins__": {}}, SAFE_FUNCTIONS)
def advanced_calculator():
print("=== Advanced Calculator ===")
print("Supports: +, -, *, /, (), functions: abs, round, min, max, sum, pow")
print("Example: max(1,2,3) + round(3.14159, 2)")
print("Type 'quit' to exit\n")
while True:
try:
expr = input("Enter expression: ").strip()
if expr.lower() == 'quit':
break
result = safe_eval(expr)
print(f"Result: {result}\n")
except Exception as e:
print(f"Error: {e}\n")
# advanced_calculator()
GUI Version: Tkinter Calculator
import tkinter as tk
from tkinter import messagebox
class CalculatorApp:
def __init__(self, root):
self.root = root
self.root.title("Python Calculator")
self.root.geometry("300x400")
self.expression = ""
# Display
self.display = tk.Entry(root, font=('Arial', 24), justify='right')
self.display.grid(row=0, column=0, columnspan=4, sticky='nsew')
# Buttons
buttons = [
('C', 1, 0), ('⌫', 1, 1), ('%', 1, 2), ('/', 1, 3),
('7', 2, 0), ('8', 2, 1), ('9', 2, 2), ('*', 2, 3),
('4', 3, 0), ('5', 3, 1), ('6', 3, 2), ('-', 3, 3),
('1', 4, 0), ('2', 4, 1), ('3', 4, 2), ('+', 4, 3),
('±', 5, 0), ('0', 5, 1), ('.', 5, 2), ('=', 5, 3),
]
for (text, row, col) in buttons:
btn = tk.Button(root, text=text, font=('Arial', 18),
command=lambda t=text: self.on_click(t))
btn.grid(row=row, column=col, sticky='nsew', padx=2, pady=2)
# Configure Grid Weights
for i in range(6):
root.rowconfigure(i, weight=1)
for i in range(4):
root.columnconfigure(i, weight=1)
def on_click(self, char):
if char == 'C':
self.expression = ""
elif char == '⌫':
self.expression = self.expression[:-1]
elif char == '=':
try:
result = eval(self.expression)
self.expression = str(result)
except Exception as e:
self.expression = "Error"
elif char == '±':
if self.expression and self.expression[0] == '-':
self.expression = self.expression[1:]
else:
self.expression = '-' + self.expression
else:
self.expression += char
self.display.delete(0, tk.END)
self.display.insert(0, self.expression)
# Run GUI
# if __name__ == "__main__":
# root = tk.Tk()
# app = CalculatorApp(root)
# root.mainloop()
Class-based Design (OOP)
class Calculator:
"""Object-Oriented Calculator"""
def __init__(self):
self.history = []
self.operations = {
'+': lambda a, b: a + b,
'-': lambda a, b: a - b,
'*': lambda a, b: a * b,
'/': self._safe_divide,
}
def _safe_divide(self, a, b):
if b == 0:
raise ZeroDivisionError("Division by zero")
return a / b
def calculate(self, a, op, b):
if op not in self.operations:
raise ValueError(f"Unknown operator: {op}")
result = self.operations[op](a, b)
self.history.append(f"{a} {op} {b} = {result}")
return result
def get_history(self):
return self.history.copy()
def clear_history(self):
self.history.clear()
# Usage
calc = Calculator()
print(calc.calculate(10, '+', 5)) # 15
print(calc.calculate(10, '/', 2)) # 5.0
print(calc.get_history()) # ['10 + 5 = 15', '10 / 2 = 5.0']
สรุป
- Basic: Function Dictionary + Loop + Error Handling
- Advanced: Safe eval() with Regex Validation + Allowlist
- GUI: Tkinter Event-driven Interface
- OOP: Class-based with History Tracking
- หลักการสำคัญ: ไม่ใช้ eval() ตรงกับ User Input โดยไม่มี Validation