Skip to content

Simple Calculator

Abstract

A calculator is the perfect second project. It is small enough to finish in one sitting and large enough to teach you the four pillars of procedural Python: functions, control flow, user input, and error handling. In this tutorial you will build a command-line calculator that performs the four basic operations plus square root and exponentiation, runs in a loop until the user chooses to exit, and handles invalid input gracefully.

By the end you will have practiced:

  • Defining and calling functions with parameters and return values.
  • Using the mathmath module from Python’s standard library.
  • Branching with ifif/elifelif/elseelse.
  • Looping with while Truewhile True plus breakbreak.
  • Converting strings from input()input() into numbers using float()float().
  • Catching errors with trytry/exceptexcept.

Prerequisites

  • Python 3.6 or above.
  • A text editor or IDE (VS Code recommended).
  • Familiarity with running a Python file from the terminal (see Hello World).

Concepts You Will Use

ConceptWhat it is
FunctionA reusable named block of code. Defined with defdef.
ParameterA variable a function expects when called.
Return valueThe result a function hands back with returnreturn.
mathmath moduleStandard-library module providing sqrtsqrt, powpow, pipi, loglog, etc.
Type conversionTurning a string like "3.14""3.14" into a float with float()float().
ExceptionAn error object Python raises when something goes wrong, such as dividing by zero.

Getting Started

Create the project

  1. Make a folder named simple-calculatorsimple-calculator.
  2. Inside it, create a file named calculator.pycalculator.py.
  3. Open the folder in your code editor.

Write the code

Paste the following into calculator.pycalculator.py:

Simple CalculatorSource
Simple Calculator
# Calculator Program
 
# Importing Modules
import math
 
# Defining Functions
def add(x, y):
    return x + y
 
def sub(x, y):
    return x - y
 
def mul(x, y):
    return  x * y
 
def div(x, y):
    return x / y
 
def sqrt(x):
    return math.sqrt(x)
 
def power(x, y):
    return math.pow(x, y)
 
 
# Main Program
print("Select Operation.")
print("1. Addition")
print("2. Subtraction")
print("3. Multiplication")
print("4. Division")
print("5. Square Root")
print("6. Power")
print("E. Exit")
print("R. Restart")
 
while True:
    choice = input("Enter Choice (1/2/3/4/5/6/E/R): ")
 
    if choice in ('1', '2', '3', '4', '5', '6'):
        num1 = float(input("Enter First Number: "))
        num2 = float(input("Enter Second Number: "))
 
        if choice == '1':
            print(num1, "+", num2, "=", add(num1, num2))
 
        elif choice == '2':
            print(num1, "-", num2, "=", sub(num1, num2))
 
        elif choice == '3':
            print(num1, "*", num2, "=", mul(num1, num2))
 
        elif choice == '4':
            print(num1, "/", num2, "=", div(num1, num2))
 
        elif choice == '5':
            print("Square Root of", num1, "=", sqrt(num1))
            print("Square Root of", num2, "=", sqrt(num2))
 
        elif choice == '6':
            print(num1, "to the power of", num2, "=", power(num1, num2))
 
    elif choice.upper() == 'E':
        confirm = input("Are you sure you want to exit? (Y/N): ")
        if confirm.upper() == 'Y':
            print("Exiting...")
            break
        elif confirm.upper() == 'N':
            print("Select Operation.")
            print("1. Addition")
            print("2. Subtraction")
            print("3. Multiplication")
            print("4. Division")
            print("5. Square Root")
            print("6. Power")
            print("E. Exit")
            print("R. Restart")
        else:
            print("Invalid Input")
 
    elif choice.upper() == 'R':
        print("Restarting...")
        print("Select Operation.")
        print("1. Addition")
        print("2. Subtraction")
        print("3. Multiplication")
        print("4. Division")
        print("5. Square Root")
        print("6. Power")
        print("E. Exit")
        print("R. Restart")
 
    else:
        print("Invalid Input")
Simple Calculator
# Calculator Program
 
# Importing Modules
import math
 
# Defining Functions
def add(x, y):
    return x + y
 
def sub(x, y):
    return x - y
 
def mul(x, y):
    return  x * y
 
def div(x, y):
    return x / y
 
def sqrt(x):
    return math.sqrt(x)
 
def power(x, y):
    return math.pow(x, y)
 
 
# Main Program
print("Select Operation.")
print("1. Addition")
print("2. Subtraction")
print("3. Multiplication")
print("4. Division")
print("5. Square Root")
print("6. Power")
print("E. Exit")
print("R. Restart")
 
while True:
    choice = input("Enter Choice (1/2/3/4/5/6/E/R): ")
 
    if choice in ('1', '2', '3', '4', '5', '6'):
        num1 = float(input("Enter First Number: "))
        num2 = float(input("Enter Second Number: "))
 
        if choice == '1':
            print(num1, "+", num2, "=", add(num1, num2))
 
        elif choice == '2':
            print(num1, "-", num2, "=", sub(num1, num2))
 
        elif choice == '3':
            print(num1, "*", num2, "=", mul(num1, num2))
 
        elif choice == '4':
            print(num1, "/", num2, "=", div(num1, num2))
 
        elif choice == '5':
            print("Square Root of", num1, "=", sqrt(num1))
            print("Square Root of", num2, "=", sqrt(num2))
 
        elif choice == '6':
            print(num1, "to the power of", num2, "=", power(num1, num2))
 
    elif choice.upper() == 'E':
        confirm = input("Are you sure you want to exit? (Y/N): ")
        if confirm.upper() == 'Y':
            print("Exiting...")
            break
        elif confirm.upper() == 'N':
            print("Select Operation.")
            print("1. Addition")
            print("2. Subtraction")
            print("3. Multiplication")
            print("4. Division")
            print("5. Square Root")
            print("6. Power")
            print("E. Exit")
            print("R. Restart")
        else:
            print("Invalid Input")
 
    elif choice.upper() == 'R':
        print("Restarting...")
        print("Select Operation.")
        print("1. Addition")
        print("2. Subtraction")
        print("3. Multiplication")
        print("4. Division")
        print("5. Square Root")
        print("6. Power")
        print("E. Exit")
        print("R. Restart")
 
    else:
        print("Invalid Input")

Save the file. Open the terminal, cdcd to the folder, and run:

command
C:\Users\username\Documents\simple-calculator> python calculator.py
Select Operation.
1. Addition
2. Subtraction
3. Multiplication
4. Division
5. Square Root
6. Power
E. Exit
R. Restart
Enter Choice (1/2/3/4/5/6/E/R): 1
Enter First Number: 2
Enter Second Number: 4
2.0 + 4.0 = 6.0
Enter Choice (1/2/3/4/5/6/E/R): E
Are you sure you want to exit? (Y/N): Y
Exiting...
command
C:\Users\username\Documents\simple-calculator> python calculator.py
Select Operation.
1. Addition
2. Subtraction
3. Multiplication
4. Division
5. Square Root
6. Power
E. Exit
R. Restart
Enter Choice (1/2/3/4/5/6/E/R): 1
Enter First Number: 2
Enter Second Number: 4
2.0 + 4.0 = 6.0
Enter Choice (1/2/3/4/5/6/E/R): E
Are you sure you want to exit? (Y/N): Y
Exiting...

Step-by-Step Explanation

1. Import the math module

calculator.py
import math
calculator.py
import math

The mathmath module gives you mathematical helpers you would otherwise have to write yourself. We use math.sqrt(x)math.sqrt(x) for square roots and math.pow(x, y)math.pow(x, y) for exponentiation. (Python also has the **** operator for powers, but using math.powmath.pow keeps the code consistent and explicit.)

2. Define one function per operation

calculator.py
def add(x, y):
    return x + y
 
def subtract(x, y):
    return x - y
 
def multiply(x, y):
    return x * y
 
def divide(x, y):
    return x / y
calculator.py
def add(x, y):
    return x + y
 
def subtract(x, y):
    return x - y
 
def multiply(x, y):
    return x * y
 
def divide(x, y):
    return x / y

Each function takes two numbers, performs one operation, and returns the result. This is separation of concerns — every piece does exactly one thing. It is easier to test, easier to read, and easier to extend.

3. The main loop

calculator.py
while True:
    print("Select Operation.")
    print("1. Addition")
    # …
    choice = input("Enter Choice (1/2/3/4/5/6/E/R): ")
calculator.py
while True:
    print("Select Operation.")
    print("1. Addition")
    # …
    choice = input("Enter Choice (1/2/3/4/5/6/E/R): ")

while Truewhile True keeps the menu visible until the user explicitly exits. Without the loop, the program would run once and quit — frustrating for anyone doing several calculations in a row.

4. Dispatching the choice

calculator.py
if choice == "1":
    num1 = float(input("Enter First Number: "))
    num2 = float(input("Enter Second Number: "))
    print(num1, "+", num2, "=", add(num1, num2))
elif choice == "2":
    # …
calculator.py
if choice == "1":
    num1 = float(input("Enter First Number: "))
    num2 = float(input("Enter Second Number: "))
    print(num1, "+", num2, "=", add(num1, num2))
elif choice == "2":
    # …
  • input()input() always returns a string. float()float() converts it to a floating-point number so arithmetic works.
  • The chain of ifif/elifelif/elseelse picks the right function based on the menu choice.
  • An elseelse at the bottom handles unknown inputs.

5. Exit confirmation

calculator.py
elif choice.upper() == "E":
    confirm = input("Are you sure you want to exit? (Y/N): ")
    if confirm.upper() == "Y":
        print("Exiting...")
        break
calculator.py
elif choice.upper() == "E":
    confirm = input("Are you sure you want to exit? (Y/N): ")
    if confirm.upper() == "Y":
        print("Exiting...")
        break

Using .upper().upper() makes the check case-insensitive — ee, EE, yy, and YY all work.

Add Robustness: Error Handling

The version above crashes if a user types abcabc when asked for a number. Add a trytry/exceptexcept block to handle it:

safer_input.py
def get_number(prompt):
    while True:
        try:
            return float(input(prompt))
        except ValueError:
            print("Please enter a valid number.")
safer_input.py
def get_number(prompt):
    while True:
        try:
            return float(input(prompt))
        except ValueError:
            print("Please enter a valid number.")

Replace each float(input(...))float(input(...)) call with get_number("...")get_number("..."). Now a typo no longer crashes the program — it asks again.

Likewise, division by zero should be friendly, not fatal:

safe_divide.py
def divide(x, y):
    if y == 0:
        return "undefined (cannot divide by zero)"
    return x / y
safe_divide.py
def divide(x, y):
    if y == 0:
        return "undefined (cannot divide by zero)"
    return x / y

Common Mistakes

ProblemWhat happenedFix
TypeError: can only concatenate strTypeError: can only concatenate strYou tried "=" + add(...)"=" + add(...) instead of using ,, in printprintUse commas in printprint or an f-string
ValueError: could not convert string to floatValueError: could not convert string to floatUser typed lettersWrap float(input(...))float(input(...)) in trytry/exceptexcept
Loop never exitsbreakbreak is indented wrong, or condition is always falseConfirm breakbreak is inside the ifif, not after it
Decimal results everywhereUsed floatfloat even for whole numbersDisplay with int(result)int(result) when you know it is whole, or format with f"{result:.2f}"f"{result:.2f}"

Variations to Try

1. More operations

more_ops.py
def modulo(x, y):     return x % y
def floor_div(x, y):  return x // y
def factorial(n):     return math.factorial(int(n))
def log(x):           return math.log(x)
more_ops.py
def modulo(x, y):     return x % y
def floor_div(x, y):  return x // y
def factorial(n):     return math.factorial(int(n))
def log(x):           return math.log(x)

2. Refactor with a dispatch dictionary

A growing ifif/elifelif chain becomes unwieldy. Replace it with a dictionary that maps choices to functions:

dispatch.py
OPERATIONS = {
    "1": ("Addition", add),
    "2": ("Subtraction", subtract),
    "3": ("Multiplication", multiply),
    "4": ("Division", divide),
}
 
choice = input("Choice: ")
if choice in OPERATIONS:
    name, func = OPERATIONS[choice]
    a, b = get_number("a: "), get_number("b: ")
    print(f"{name}: {func(a, b)}")
dispatch.py
OPERATIONS = {
    "1": ("Addition", add),
    "2": ("Subtraction", subtract),
    "3": ("Multiplication", multiply),
    "4": ("Division", divide),
}
 
choice = input("Choice: ")
if choice in OPERATIONS:
    name, func = OPERATIONS[choice]
    a, b = get_number("a: "), get_number("b: ")
    print(f"{name}: {func(a, b)}")

Adding a new operation is now one line.

3. Expression evaluator

Instead of menu-driven input, parse a typed expression like 2 + 3 * 42 + 3 * 4:

expr.py
import ast, operator as op
 
OPS = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul, ast.Div: op.truediv}
 
def evaluate(node):
    if isinstance(node, ast.Constant):
        return node.value
    if isinstance(node, ast.BinOp):
        return OPS[type(node.op)](evaluate(node.left), evaluate(node.right))
    raise ValueError("unsupported")
 
tree = ast.parse("2 + 3 * 4", mode="eval")
print(evaluate(tree.body))   # 14
expr.py
import ast, operator as op
 
OPS = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul, ast.Div: op.truediv}
 
def evaluate(node):
    if isinstance(node, ast.Constant):
        return node.value
    if isinstance(node, ast.BinOp):
        return OPS[type(node.op)](evaluate(node.left), evaluate(node.right))
    raise ValueError("unsupported")
 
tree = ast.parse("2 + 3 * 4", mode="eval")
print(evaluate(tree.body))   # 14

This safely evaluates math expressions without using the dangerous built-in eval()eval().

4. GUI calculator

Use Tkinter to build buttons in a grid. See the Calculator GUI project on Python Central Hub for a full walkthrough.

5. Calculation history

Keep a list of past results and let the user reuse the previous answer with ansans:

history.py
history = []
# after each successful calc:
history.append(result)
# allow input "ans" to mean history[-1]
history.py
history = []
# after each successful calc:
history.append(result)
# allow input "ans" to mean history[-1]

Best Practices Demonstrated

  • One function, one job. Each operation is its own function.
  • Use the standard library. mathmath is already there — do not roll your own square root.
  • Validate at the boundary. Convert and check input the moment it enters the program.
  • Handle errors close to where they happen. Division by zero is a divide()divide() problem, not a whole program problem.

Real-World Applications

  • Interactive shells for scientific work (think mini-REPL).
  • Form back-ends that compute totals from user input.
  • Bot commands (!calc 2+2!calc 2+2) in Discord/Slack integrations.
  • Foundations for spreadsheet engines and expression evaluators.

Next Steps

Extend the calculator with any of these:

  • Trigonometry: math.sinmath.sin, math.cosmath.cos, math.tanmath.tan (remember to convert degrees with math.radiansmath.radians).
  • Memory keys: M+M+, M-M-, MRMR, MCMC like a real desktop calculator.
  • Calculation history file: persist results to history.txthistory.txt so they survive restarts.
  • Unit conversion mode: kilometers ↔ miles, kilograms ↔ pounds, etc.
  • Graphing mode: pair with matplotlibmatplotlib to plot a function the user types.

Conclusion

A calculator looks simple, but it is one of the most honest beginner projects: every feature you add forces you to write better code. You used Python’s built-in mathmath module, separated each operation into its own function, looped a menu, and converted user input safely. Find more progressive beginner projects on Python Central Hub. The full source is on GitHub.

If this helped you, consider buying me a coffee ☕

Buy me a coffee

Was this page helpful?

Let us know how we did