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
mathmathmodule from Python’s standard library. - Branching with
ifif/elifelif/elseelse. - Looping with
while Truewhile Trueplusbreakbreak. - Converting strings from
input()input()into numbers usingfloat()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
| Concept | What it is |
|---|---|
| Function | A reusable named block of code. Defined with defdef. |
| Parameter | A variable a function expects when called. |
| Return value | The result a function hands back with returnreturn. |
mathmath module | Standard-library module providing sqrtsqrt, powpow, pipi, loglog, etc. |
| Type conversion | Turning a string like "3.14""3.14" into a float with float()float(). |
| Exception | An error object Python raises when something goes wrong, such as dividing by zero. |
Getting Started
Create the project
- Make a folder named
simple-calculatorsimple-calculator. - Inside it, create a file named
calculator.pycalculator.py. - Open the folder in your code editor.
Write the code
Paste the following into calculator.pycalculator.py:
Simple Calculator
Source# 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")# 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:
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...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
import mathimport mathThe 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
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 / ydef 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 / yEach 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
while True:
print("Select Operation.")
print("1. Addition")
# …
choice = input("Enter Choice (1/2/3/4/5/6/E/R): ")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
if choice == "1":
num1 = float(input("Enter First Number: "))
num2 = float(input("Enter Second Number: "))
print(num1, "+", num2, "=", add(num1, num2))
elif choice == "2":
# …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/elseelsepicks the right function based on the menu choice. - An
elseelseat the bottom handles unknown inputs.
5. Exit confirmation
elif choice.upper() == "E":
confirm = input("Are you sure you want to exit? (Y/N): ")
if confirm.upper() == "Y":
print("Exiting...")
breakelif choice.upper() == "E":
confirm = input("Are you sure you want to exit? (Y/N): ")
if confirm.upper() == "Y":
print("Exiting...")
breakUsing .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:
def get_number(prompt):
while True:
try:
return float(input(prompt))
except ValueError:
print("Please enter a valid number.")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:
def divide(x, y):
if y == 0:
return "undefined (cannot divide by zero)"
return x / ydef divide(x, y):
if y == 0:
return "undefined (cannot divide by zero)"
return x / yCommon Mistakes
| Problem | What happened | Fix |
|---|---|---|
TypeError: can only concatenate strTypeError: can only concatenate str | You tried "=" + add(...)"=" + add(...) instead of using ,, in printprint | Use commas in printprint or an f-string |
ValueError: could not convert string to floatValueError: could not convert string to float | User typed letters | Wrap float(input(...))float(input(...)) in trytry/exceptexcept |
| Loop never exits | breakbreak is indented wrong, or condition is always false | Confirm breakbreak is inside the ifif, not after it |
| Decimal results everywhere | Used floatfloat even for whole numbers | Display 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
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)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:
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)}")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:
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)) # 14import 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)) # 14This 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 = []
# after each successful calc:
history.append(result)
# allow input "ans" to mean history[-1]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.
mathmathis 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 withmath.radiansmath.radians). - Memory keys:
M+M+,M-M-,MRMR,MCMClike a real desktop calculator. - Calculation history file: persist results to
history.txthistory.txtso they survive restarts. - Unit conversion mode: kilometers ↔ miles, kilograms ↔ pounds, etc.
- Graphing mode: pair with
matplotlibmatplotlibto 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 coffeeWas this page helpful?
Let us know how we did
