27 — Calculator — a command-line project
A calculator that reads 3 + 4 and answers, then asks again until you type
quit, is a complete small project. It uses all three levels in one program:
beginner ask for input, plain Python while True: and def for the loop and
the math, and NME show for output.
Steps
Save the whole calculator in one file,
calculator.nme, and run it:
run it →# A command-line calculator: type 3 + 4, or quit. # Run: nme r calculator def calculate(parts): if parts[1] == "+": return int(parts[0]) + int(parts[2]) elif parts[1] == "-": return int(parts[0]) - int(parts[2]) elif parts[1] == "*": return int(parts[0]) * int(parts[2]) else: return int(parts[0]) / int(parts[2]) show "Calculator — type a command like 3 + 4, or quit." while True: ask command, "Your command? " if command == "quit": show "Bye!" break parts = command.split() if len(parts) == 3: answer = calculate(parts) show f"{command} = {answer}" else: show "Use the form: number operator number"printf '3 + 4\n10 - 3\n7 * 6\n10 / 4\nquit\n' | nme r calculatorCalculator — type a command like 3 + 4, or quit. Your command? 3 + 4 = 7 Your command? 10 - 3 = 7 Your command? 7 * 6 = 42 Your command? 10 / 4 = 2.5 Your command? Bye!The math lives in a function.
defnames it,partsholds the split command, andreturnsends the answer back.parts[1]is the operator andint(parts[0])turns the text"3"into the number3:
run it →def calculate(parts): if parts[1] == "+": return int(parts[0]) + int(parts[2]) elif parts[1] == "-": return int(parts[0]) - int(parts[2]) elif parts[1] == "*": return int(parts[0]) * int(parts[2]) else: return int(parts[0]) / int(parts[2])elifchains one branch per operator; the lastelseis division. This block is advanced Python written directly inside the NME file.split()cuts the command into words."3 + 4".split()becomes['3', '+', '4'], soparts[0]is the first number,parts[1]the operator,parts[2]the second number.len(parts) == 3rejects anything that is not a well-formed command:
run it →parts = command.split() if len(parts) == 3: answer = calculate(parts) show f"{command} = {answer}" else: show "Use the form: number operator number"show f"{command} = {answer}"prints the line you typed and the result on one row.The loop is the same shape as the menu in 22:
while True:never ends on its own, soquitmustbreakout. Everything between is one turn of the calculator:
run it →while True: ask command, "Your command? " if command == "quit": show "Bye!" break parts = command.split() if len(parts) == 3: answer = calculate(parts) show f"{command} = {answer}" else: show "Use the form: number operator number"Once the function works, move it into its own module as guide 23 showed. Save the function in
calc.nme:
run it →# calc.nme — the calculate function only def calculate(parts): if parts[1] == "+": return int(parts[0]) + int(parts[2]) elif parts[1] == "-": return int(parts[0]) - int(parts[2]) elif parts[1] == "*": return int(parts[0]) * int(parts[2]) else: return int(parts[0]) / int(parts[2])Then import it at the top of
calculator.nme. The main file now only describes the loop; the math stays incalc.nme:from "calc.nme" import calculate show "Calculator — type a command like 3 + 4, or quit." while True: ask command, "Your command? " if command == "quit": show "Bye!" break parts = command.split() if len(parts) == 3: answer = calculate(parts) show f"{command} = {answer}" else: show "Use the form: number operator number"nme check calculatorchecks both files, andnme r calculatorruns the import just like before.The Korean twin
calculator.ko.nmekeeps the samedefand writes the loop with물어봐,만약, and말해:
run it →def calculate(parts): if parts[1] == "+": return int(parts[0]) + int(parts[2]) while True: 물어봐 command, "명령을 입력하세요? " 만약 command == "quit": 말해 "안녕!" break parts = command.split() answer = calculate(parts) 말해 f"{command} = {answer}"The same piped input produces the same answers in both languages.
Try it yourself
Add a fifth operator: change the else branch so // means floor division
(int(parts[0]) // int(parts[2])), then test 17 // 5. Or make the unknown
operator a friendly message instead of dividing.
What you learned
def/returnpackage the math into one reusable function.command.split()cuts a line into parts;int(parts[0])reads a number.while True:withbreakonquitmakes a repeat-until-quit loop.- Moving the function to a
.nmemodule keeps the project clean.