What You'll Build

A Python command-line calculator that runs in the terminal. It shows a menu of operations, asks for two numbers, prints the result, and loops back for the next calculation. Type q to quit. Invalid input is caught and shown gracefully instead of crashing.

  • Menu-driven interface — add, subtract, multiply, divide, power
  • Reads numbers from the user with input()
  • Keeps running until you quit
  • Handles invalid input without crashing
  • Prevents division by zero gracefully
  • Keeps a history of all calculations
▶ Terminal Preview — simulated Python session (click and type)

Note about the preview: Python runs on your computer, not in a browser. This preview is a simulated terminal that mimics the exact behaviour of the finished calculator. When you run the real code, it will look like this in your terminal.

What You'll Learn

0

Make Sure Python Is Installed

If you haven't installed Python yet, follow our guide — it takes 5 minutes:

Verify Python is installed by opening a terminal and typing:

Terminal
python --version

You should see something like Python 3.12.0. If not, install it first and come back.

1

Start with the Simplest Version

Create a file called calculator.py. We'll build this in stages — start with the simplest possible version, then improve it.

Python
# calculator.py — version 1
print("Simple Calculator")

a = float(input("Enter first number: "))
b = float(input("Enter second number: "))

print(f"{a} + {b} = {a + b}")
print(f"{a} - {b} = {a - b}")
print(f"{a} * {b} = {a * b}")

Run it:

Terminal
python calculator.py

Working calculator. It runs, asks for two numbers, prints three results, and exits. Now we make it useful.

Why float(input())? input() always returns a string — even if the user types a number. float() converts that string to a decimal number. Without it, "5" + "3" gives "53" instead of 8.

2

Add a Menu and Let the User Choose

Now the calculator asks which operation to perform. We use if / elif / else to branch based on the user's choice.

Python
# calculator.py — version 2
print("=== Python Calculator ===")
print("1. Add")
print("2. Subtract")
print("3. Multiply")
print("4. Divide")
print("5. Power")
print()

choice = input("Choose an operation (1-5): ")
a = float(input("Enter first number: "))
b = float(input("Enter second number: "))

if choice == "1":
    result = a + b
    print(f"{a} + {b} = {result}")
elif choice == "2":
    result = a - b
    print(f"{a} - {b} = {result}")
elif choice == "3":
    result = a * b
    print(f"{a} * {b} = {result}")
elif choice == "4":
    result = a / b
    print(f"{a} / {b} = {result}")
elif choice == "5":
    result = a ** b
    print(f"{a} ^ {b} = {result}")
else:
    print("Invalid choice.")

Now the user picks what they want. But there are still problems:

Let's fix all three.

3

Wrap Everything in a Loop

To keep running until the user quits, wrap the whole program in a while loop. We use the special value True for an infinite loop that only ends when we break out of it.

Python
# calculator.py — version 3
while True:
    print("\n=== Python Calculator ===")
    print("1. Add      2. Subtract")
    print("3. Multiply 4. Divide")
    print("5. Power    q. Quit")

    choice = input("\nChoose an operation: ").strip().lower()

    if choice == "q":
        print("Goodbye!")
        break

    # ... rest of the calculator here ...

What's .strip().lower()? .strip() removes whitespace from both ends (so " q " becomes "q"). .lower() makes everything lowercase (so "Q" becomes "q"). This makes the program more forgiving — the user doesn't have to type perfectly.

4

Add Error Handling

Now the important part — catching errors instead of crashing. Python uses try / except for this.

Python
# Wrapping risky code in try/except

try:
    a = float(input("Enter first number: "))
    b = float(input("Enter second number: "))
except ValueError:
    print("❌ That's not a valid number. Try again.")
    continue  # jump back to the top of the while loop

ValueError is what float() raises when it can't convert a string to a number. If the user types "abc" and we try float("abc"), Python raises that error. Our except catches it, prints a friendly message, and continue skips to the next iteration of the loop.

For division by zero, we handle it inline:

Python
elif choice == "4":
    if b == 0:
        print("❌ Cannot divide by zero.")
        continue
    result = a / b
    print(f"{a} / {b} = {result}")
5

Extract Functions for Cleaner Code

The code is getting long. Time to break it into functions. Each one does a single job — this is how real Python code is written.

Python — Part 1: Functions
# calculator.py — final version

def show_menu():
    """Print the main menu."""
    print("\n=== Python Calculator ===")
    print("1. Add      2. Subtract")
    print("3. Multiply 4. Divide")
    print("5. Power    h. History")
    print("q. Quit")

def get_numbers():
    """Ask the user for two numbers. Returns them or None on error."""
    try:
        a = float(input("Enter first number: "))
        b = float(input("Enter second number: "))
        return a, b
    except ValueError:
        print("❌ That's not a valid number.")
        return None

def calculate(choice, a, b):
    """Perform the chosen operation. Returns result or None on error."""
    if choice == "1":
        return a + b, "+"
    elif choice == "2":
        return a - b, "-"
    elif choice == "3":
        return a * b, "*"
    elif choice == "4":
        if b == 0:
            print("❌ Cannot divide by zero.")
            return None, None
        return a / b, "/"
    elif choice == "5":
        return a ** b, "^"
    else:
        print("❌ Invalid choice.")
        return None, None
6

Add a History Feature

To make it more useful, keep a list of every calculation the user performs. A list works perfectly for this.

Python — Part 2: Main Loop
def main():
    """The main program loop."""
    history = []  # empty list to start

    print("Welcome to the Python Calculator!")

    while True:
        show_menu()
        choice = input("\nChoose: ").strip().lower()

        # Quit
        if choice == "q":
            print("\nGoodbye! 👋")
            break

        # Show history
        if choice == "h":
            if not history:
                print("No calculations yet.")
            else:
                print("\n--- History ---")
                for i, entry in enumerate(history, 1):
                    print(f"{i}. {entry}")
            continue

        # Get numbers
        nums = get_numbers()
        if nums is None:
            continue

        a, b = nums

        # Calculate
        result, op = calculate(choice, a, b)
        if result is None:
            continue

        # Show result
        line = f"{a} {op} {b} = {result}"
        print(f"\n✅ {line}")
        history.append(line)

# Only run when this file is executed directly
if __name__ == "__main__":
    main()

Save the file and run it: python calculator.py. The calculator should greet you, show the menu, and accept input. Type h to see the history. Type q to quit.

7

Understand the Big Ideas

1. Why input() always returns a string

Python's input() function is designed to accept any text — names, sentences, phone numbers, whatever. It can't guess that you want a number. So it always returns a string. You convert with int() or float() when you need a number.

Python
age = input("Your age: ")   # age is a string, e.g. "25"
age = int(age)               # now it's a number, 25

# Or in one line:
age = int(input("Your age: "))

2. try / except — Python's version of try / catch

Same idea as JavaScript's try / catch, different keyword. In Python:

Python
try:
    result = int("hello")
except ValueError:
    print("That's not a number.")

You can catch different error types (ValueError, ZeroDivisionError, FileNotFoundError) and handle each differently. Catching the specific error you expect is better than catching everything — it hides bugs.

3. f-strings — the cleanest way to format strings

Python
name = "Sarah"
age = 25

# Old ways (avoid):
print("Hello, " + name + ". You are " + str(age) + ".")
print("Hello, {}. You are {}.".format(name, age))

# f-string (use this):
print(f"Hello, {name}. You are {age}.")

f-strings are faster, more readable, and let you embed expressions directly: f"Next year you'll be {age + 1}".

4. continue vs break

In our calculator, when the user enters an invalid number, we continue — skip everything else this round and show the menu again. When they type q, we break — exit for good.

5. The if __name__ == "__main__" pattern

Every real Python file ends with this line. It means: "only run main() if this file is executed directly — not if it's imported by another file."

You don't need to fully understand this yet. Just know that it's the standard way to write a Python program's entry point. Add it to every script you write.

8

Practice Challenges

🟢 Beginner

🟡 Intermediate

🔴 Advanced

Full Source Code

The complete calculator.py in one block:

Python — complete file
"""calculator.py — a command-line calculator."""

def show_menu():
    print("\n=== Python Calculator ===")
    print("1. Add      2. Subtract")
    print("3. Multiply 4. Divide")
    print("5. Power    h. History")
    print("q. Quit")

def get_numbers():
    try:
        a = float(input("Enter first number: "))
        b = float(input("Enter second number: "))
        return a, b
    except ValueError:
        print("❌ That's not a valid number.")
        return None

def calculate(choice, a, b):
    if choice == "1":
        return a + b, "+"
    elif choice == "2":
        return a - b, "-"
    elif choice == "3":
        return a * b, "*"
    elif choice == "4":
        if b == 0:
            print("❌ Cannot divide by zero.")
            return None, None
        return a / b, "/"
    elif choice == "5":
        return a ** b, "^"
    else:
        print("❌ Invalid choice.")
        return None, None

def main():
    history = []
    print("Welcome to the Python Calculator!")

    while True:
        show_menu()
        choice = input("\nChoose: ").strip().lower()

        if choice == "q":
            print("\nGoodbye! 👋")
            break

        if choice == "h":
            if not history:
                print("No calculations yet.")
            else:
                print("\n--- History ---")
                for i, entry in enumerate(history, 1):
                    print(f"{i}. {entry}")
            continue

        nums = get_numbers()
        if nums is None:
            continue

        a, b = nums
        result, op = calculate(choice, a, b)
        if result is None:
            continue

        line = f"{a} {op} {b} = {result}"
        print(f"\n✅ {line}")
        history.append(line)

if __name__ == "__main__":
    main()

Common Mistakes & Fixes

❌ "SyntaxError: invalid syntax" on print

In Python 3, print is a function and needs parentheses: print("hello"), not print "hello". If you're following Python 2 tutorials, they'll be wrong for modern Python.

❌ "TypeError: can only concatenate str (not 'int') to str"

You're trying to add a string and a number: "Age: " + 25. Fix it with an f-string: f"Age: {25}", or convert: "Age: " + str(25).

❌ "NameError: name 'x' is not defined"

You're using a variable before creating it, or you have a typo in the name. Python is case-sensitive — Age and age are different variables.

❌ "IndentationError"

Python uses indentation (whitespace) to define code blocks — not curly braces like JavaScript. Every line inside a function, if statement, or loop must be indented consistently. Use 4 spaces (not tabs).

❌ "ValueError: could not convert string to float: 'abc'"

The user typed something that isn't a number. Wrap the conversion in try/except (as shown in step 4).

❌ "ZeroDivisionError"

Division by zero raises this in Python. Check b == 0 before dividing, or catch the error in try/except.

❌ Program exits after one calculation

You forgot the while True: loop. Without it, the program runs top-to-bottom once and exits.

What to Build Next