
A Python calculator is a small command-line program: you type an expression like 7 * 6, it prints the answer, and it waits for the next one. Your phone already does this. The difference is that you'll understand every line of yours, and you'll make it parse input, survive bad keystrokes and keep running until you type q.
The whole build is four steps in one file. You won't install any libraries. You only need Python's standard toolkit: the operator module, input(), float() and a while loop. Along the way you'll see why a dictionary of functions beats both long if-else chains and the risky shortcut of eval().
- A single dictionary maps +, -, * and / to functions from Python's operator module.
- input() reads the line, and split() breaks it into number, operator, number.
- float() converts the text to numbers, and OPSop(a, b) does the math in one line.
- A while True loop keeps the calculator running until the user types q.
- try/except with named errors stops crashes. Never run eval() on user input.
- 0:00Intro
- 0:21What you'll build and need
- 0:59Map operators to functions
- 1:46Read and split the input
- 2:31Convert and look up the operator
- 3:17Wrap it in a while loop
- 3:57Test it with real math
- 4:39Fix the crashes before users do
- 5:32Four steps to a smarter calculator
- 5:56A dictionary beats eval(), every time
Gather what you need before you start
Pin down the target first. You type 7 * 6 in your terminal, you get the answer, and then you type another expression. The calculator reads what you type, does the math, survives bad input and loops until you quit. That covers the whole spec.
Why build your own when your phone has one? Yours will parse whatever you throw at it, and it won't fall over when you hit the wrong key. Along the way you'll practise skills that carry into any Python script that takes user input.
The list of requirements is short. One item does more work than the others: dictionaries. A dictionary drives this entire build, so you should be comfortable creating one and looking up values in it before you begin.
- Python 3 is installed and runs from your terminal
- A code editor is open (any one will do)
- You're comfortable writing and calling functions
- You're comfortable with dictionaries and key lookups
Map operators to functions with a dictionary
Step one replaces a tangle of if-else checks with a lookup table. Think of it as a phone book. You give it a plus sign, and it hands back the function that adds. The first line imports the operator module. Then a dictionary called OPS maps each symbol to a real Python function.
The symbols map like this. + goes to operator.add, - to operator.sub, * to operator.mul, and / to operator.truediv. Truediv means true division, so 10 / 4 gives 2.5 rather than a rounded-down result. That detail matters again when you test the calculator.
Why is this better than if-statements? You handle four symbols with zero branches. If you want a new operator later, such as power, you add one more line to the dictionary instead of another elif. These functions also ship with Python's standard library, so they're tested and fast. Your whole math engine fits in five lines.
- import operator sits at the top of the file
- OPS contains exactly four keys: +, -, *, /
- Division uses operator.truediv, not floor division
- The file has no if-chains for choosing the operation
import operator
OPS = {
'+': operator.add, '-': operator.sub,
'*': operator.mul, '/': operator.truediv,
}
Read and split the input into three parts
The engine exists. Now it needs fuel. Two built-ins do all the work. input() reads the whole line the user types as one string. split() then chops that string wherever there's a space.
Here's how 7 * 6 travels through the code. The keystrokes are seven, space, star, space, six. split() breaks the line at each space and gives you three strings: '7', '*' and '6'. You unpack them into three variables, so a is '7', op is '*' and b is '6'.
Notice the quotes. These values are still text. If you add '7' and '6' now, Python glues them together into '76' instead of doing math. Spacing also matters. split() with no argument splits on whitespace, so the user has to type spaces around the operator. Without them you won't get three clean pieces.
- input() returns one string for the whole line
- split() with no argument splits on whitespace
- Unpacking gives you a, op and b
- All three values are still strings at this point
Convert the numbers and look up the operator
This is where the calculation happens. The three strings from step two meet the dictionary from step one. Follow 7 * 6 through it. float('7') becomes 7.0. float('6') becomes 6.0. OPS'*' returns operator.mul. Calling mul with 7.0 and 6.0 gives 42.0.
Why float() instead of int()? With float, decimals just work, so 2.5 * 4 is no problem. The trade-off is that every answer prints with a decimal point, even whole numbers like 42.0. For a general-purpose calculator, that's a fair price.
The neatest part is treating a function as a value. OPSop gives you a function, and the parentheses right after it call that function with your two numbers. OPSop(a, b) handles the lookup and the math in a single line.
- Both numbers go through float() before any math
- OPSop returns a function rather than a result
- OPSop(a, b) returns the answer
- 7 * 6 produces 42.0
Wrap it in a while loop so it keeps going
Right now the script calculates once and stops. One loop turns that one-shot script into a tool you can keep typing into. The cycle has four beats. Show a prompt, check whether the user typed q, calculate, and print the result. Then it starts again.
In the code, while True loops forever. A variable called line takes the input. If line equals 'q', the loop hits break and exits. Otherwise the code splits the line and prints OPSop called on the two floats.
That q check makes a real difference. Without it, the only way out is Ctrl-C, which leaves an ugly traceback in the terminal. With it, the user types q and the program ends cleanly. It's a small touch that makes your calculator feel like a finished tool.
- The loop uses while True
- The q check runs before any splitting or math
- break exits the loop cleanly
- Quitting doesn't require Ctrl-C
while True:
line = input('> ')
if line == 'q':
break
a, op, b = line.split()
print(OPS[op](float(a), float(b)))
Test it with math you already know
Now prove it works. Save the file as calc.py, open your terminal in that folder and run python3 calc.py. At the prompt, try 7 * 6. If you see 42.0, the core path works.
Next, try 10 / 4. This is the real check. With floor division you'd get 2.0, so seeing 2.5 confirms that truediv is wired correctly. Finally, type q. You should land back at the $ prompt with no error message.
Choose test inputs whose answers you already know. When the expected result is obvious, any mismatch points straight at the step that's broken. Three tests and three passes mean you have a working calculator.
- 7 * 6 prints 42.0
- 10 / 4 prints 2.5, not 2.0
- q returns you to the $ prompt
- No traceback appears at any point
python3 calc.py
Fix the crashes before your users find them
Your calculator works on perfect input, but real users don't type perfect input. Every fix lives in one try block wrapped around the calculation, with an except clause for each error type. Here's what breaks and why.
Dividing by zero, as in 5 / 0, raises ZeroDivisionError, so catch it and print a friendly warning. Typing a non-number such as abc makes float() raise ValueError, so catch it and ask again. Typing 7*6 without spaces won't unpack into three pieces, which is another ValueError. An unknown symbol like % isn't in OPS, so the lookup raises KeyError. Check for that case first.
Name each error you catch. A bare except swallows everything, including genuine bugs in your own code that you'd want to see. Catching specific exceptions keeps the calculator running while real problems still surface.
- ZeroDivisionError is caught with a friendly message
- ValueError is caught for bad numbers and missing spaces
- Unknown operators are handled before the KeyError
- The code has no bare except clause
Choose a dictionary over eval() every time
eval() is tempting because it runs a whole string as Python, so it looks like a one-line calculator. On user input, though, it means anyone can run any code on your machine. Treat that as a security hole, not a shortcut.
A dictionary of functions is safer and cleaner. It only does what you've explicitly allowed: four operators, each mapped to a tested standard-library function. To recap the build, you map operators, split the input, convert with float(), loop until q, and catch errors. Each step builds on the one before it, so if something breaks, check the previous step.
- The code never calls eval() on user input
- Only operators listed in OPS can run
- When debugging, check the step before the one that failed
The bottom line
- A dictionary that maps symbols to operator functions replaces if-else chains.
- input() plus split() turns one typed line into three usable pieces.
- float() handles decimals, at the cost of a .0 on whole-number answers.
- A while True loop with a q check makes a clean, reusable tool.
- Catch ZeroDivisionError and ValueError by name, and never use a bare except.
- Never run eval() on user input.
Quick-fire questions
Why use a dictionary instead of if-else statements in a Python calculator?
A dictionary maps each operator symbol directly to a function, so you choose the operation with one lookup instead of a chain of branches. Adding a new operator takes one extra line in the dictionary.
Why does my calculator print 42.0 instead of 42?
The numbers are converted with float(), so every result is a floating-point number with a decimal point. That's the trade-off for letting decimals like 2.5 work without extra code.
Is it safe to use eval() to build a calculator?
No. eval() runs any string as Python code, so a user could execute any code on your machine. A dictionary of operator functions only allows the operations you've defined.
Why does typing 7*6 without spaces cause an error?
split() with no argument breaks the line on whitespace, so 7*6 stays as one piece and can't be unpacked into three values. That raises a ValueError, which you can catch and use to ask the user again.
How do I stop a Python calculator from crashing on bad input?
Wrap the calculation in a try block and add an except clause for each specific error, such as ZeroDivisionError and ValueError. Avoid a bare except so genuine bugs still show up.
What's the difference between truediv and floor division?
operator.truediv performs true division, so 10 / 4 gives 2.5. Floor division would give 2.0, which is why 10 / 4 is a useful test that your calculator divides correctly.