Advertisement
🧮 Projects

Python Calculator – CLI Project

Build a fully functional command-line calculator with operation history and error handling. Perfect first Python project covering OOP, error handling, and user input.

⏱️ 20 min read🎯 Projects📅 Updated 2026

Complete Implementation

Python
import math
import operator

class Calculator:
    OPERATIONS = {
        "+": operator.add, "-": operator.sub,
        "*": operator.mul, "/": operator.truediv,
        "**": operator.pow, "%": operator.mod,
    }

    def __init__(self):
        self.history = []

    def calculate(self, a, op, b):
        if op not in self.OPERATIONS:
            raise ValueError(f"Unknown operator: {op}")
        if op == "/" and b == 0:
            raise ZeroDivisionError("Cannot divide by zero")
        result = self.OPERATIONS[op](a, b)
        self.history.append(f"{a} {op} {b} = {result}")
        return result

    def sqrt(self, n):
        if n < 0:
            raise ValueError("Cannot take sqrt of negative number")
        result = math.sqrt(n)
        self.history.append(f"sqrt({n}) = {result}")
        return result

def main():
    calc = Calculator()
    print("Python Calculator  |  ops: + - * / ** %  |  sqrt   |  history  |  quit")
    while True:
        try:
            expr = input("> ").strip().lower()
            if expr == "quit": break
            if expr == "history":
                print("\n".join(f"  {i+1}. {e}" for i, e in enumerate(calc.history)) or "No history.")
                continue
            if expr.startswith("sqrt "):
                print(calc.sqrt(float(expr[5:])))
                continue
            parts = expr.split()
            if len(parts) == 3:
                a, op, b = float(parts[0]), parts[1], float(parts[2])
                print(calc.calculate(a, op, b))
            else:
                print("Format: <num> <op> <num>")
        except (ValueError, ZeroDivisionError) as e:
            print(f"Error: {e}")
        except KeyboardInterrupt:
            break

if __name__ == "__main__":
    main()

Running

Bash
python calculator.py
# > 5 + 3       → 8.0
# > sqrt 16     → 4.0
# > history
Tip: Add a Tkinter GUI using the same Calculator class — great practice for separating logic from presentation.

🏋️ Practical Exercise

Enhance the calculator:

  1. Add support for exponentiation and modulo operations.
  2. Handle division by zero gracefully instead of crashing.
  3. Loop so the user can perform multiple calculations until they quit.
  4. Validate input so non-numeric entries show a friendly error.

🔥 Challenge Exercise

Turn the calculator into a small expression evaluator that respects operator precedence (e.g. handle 2 + 3 * 4 correctly), support parentheses, and keep a history of previous results the user can reference. Structure the code into clear functions and add error handling for malformed input. Bonus: add unit tests for the core evaluation logic.

📋 Summary

  • This project builds an interactive command-line calculator.
  • Core operations are organized into small, testable functions.
  • User input is validated and converted safely with error handling.
  • Division by zero and bad input are handled gracefully rather than crashing.
  • A loop lets the user perform repeated calculations until they quit.
  • The logic can be extended with precedence, history, tests, or a GUI.

Interview Questions on Building a Calculator

  • How would you structure a calculator program into functions?
  • How do you handle invalid or non-numeric user input?
  • How do you prevent a division-by-zero crash?
  • How would you support operator precedence?
  • How do you keep a CLI program running until the user chooses to exit?
  • How would you add unit tests for the calculation logic?
  • How could you extend it into a GUI or web app?

FAQ

How do I stop the calculator from crashing on bad input? +

Wrap the input conversion in try/except ValueError and re-prompt, and check for division by zero before dividing. Handling these edge cases turns a crash into a friendly message.

How would I handle operator precedence? +

For full expressions like 2 + 3 * 4, parse the input rather than evaluating left-to-right — implement the shunting-yard algorithm, build an expression tree, or (carefully, with trusted input only) use Python’s own parsing. A simple menu-driven calculator avoids this by doing one operation at a time.

Should I use eval() to evaluate expressions? +

Avoid eval() on untrusted input — it can execute arbitrary code. For learning with your own input it works, but a real tool should use a safe parser or ast.literal_eval for limited cases.

How could I turn this into a GUI app? +

Reuse the calculation functions and add a front end — tkinter for a desktop GUI, or a small Flask/FastAPI app for a web version. Keeping logic separate from the interface makes this swap easy.