这样做的目的是接受一个英文的数学运算串,并从左到右对它进行计算。
关于操作顺序:当大声说出操作时,通常用隐含的括号表示从左到右的链。
例如:
4加3乘2平方=== ((4+ 3)乘以2)
人们所说的节奏决定了在乘积之前是否要将2相乘,但在这种情况下,目标是严格地从左向右。
我在这里回顾的起点是我对StackOverflow问题的回答,它是直接的,正确的,但在设计和风格上不令人满意。
import math
import re
import operator
# try "3 add 4 times 5"
inputs = input(">").lower()
# Using RE to find all numbers in string.
numInString = [int(d) for d in re.findall(r'-?\d+', inputs)]
inputs = inputs.split()
print('Numbers found: ', numInString)
print('Inputs found: ', inputs)
# Define all of the operators
def multiplication():
multAns = operator.mul(numInString.pop(0) , numInString.pop(0))
numInString.insert(0, multAns)
print(multAns)
def division():
divAns = operator.truediv(numInString.pop(0) , numInString.pop(0))
numInString.insert(0, divAns)
print(divAns)
def addition():
addAns = operator.add(numInString.pop(0) , numInString.pop(0))
numInString.insert(0, addAns)
print(addAns)
def subtraction():
subAns = operator.sub(numInString.pop(0) , numInString.pop(0))
numInString.insert(0, subAns)
print(subAns)
def squareRoot():
SqrtAns = math.sqrt(numInString.pop(0))
numInString.insert(0, SqrtAns)
print(SqrtAns)
def squared():
SquareAns = math.pow(numInString.pop(0), 2)
numInString.insert(0, SquareAns)
print(SquareAns)
def cubed():
CubedAns = math.pow(numInString.pop(0), 3)
numInString.insert(0, CubedAns)
print(CubedAns)
def power():
PowerAns = math.pow(numInString.pop(0), numInString[1])
numInString.insert(0, PowerAns)
print(PowerAns)
# Dictionary mapping search words to operator function
Operation = {
'multiply': multiplication,
'times' : multiplication,
'multiplied': multiplication,
'divide': division,
'divided': division,
'into': division,
'add': addition,
'sum': addition,
'added': addition,
'subtract': subtraction,
'minus': subtraction,
'take': subtraction,
'subtracted': subtraction,
}
for words in inputs:
if words in Operation:
print(Operation[words]())Operation和numInString是好名字吗?numInString)中,而不是将它们传递给运算符函数?int类型可以吗?input('>') )?发布于 2017-12-11 20:42:13
很好的问题是,Python有一个广泛而又平易近人的风格指南,叫做PEP8。具体来说,局部变量应该是lowercase,全局常量应该是UPPERCASE,并且应该避免全局变量。
为了以后使用它,您应该返回值:
而不是:print(multAns) do return multAns
不,将数字传递给运算符并保存返回的结果。
result = oper(a=1, b=3)而不是
a = 1
b = 3
oper()print错误吗?:打印(“没有给定的操作”)不,当你遇到这种情况的时候,就会产生错误。
ValueError("Cannot match an operator to \"{}\"".format(inputstring))int吗?处理十进制数的情况会更好,特别是如果您希望能够进行真正的除法(在代码中)。
用大量的评论
import re
from decimal import Decimal字典映射搜索词到操作符函数
operations = {
'<a> (times|multiplied by) <b>':
lambda a, b: a * b,
'<a> divided by <b>':
lambda a, b: a / b,
'(add|sum)? <a> (and|plus) <b>':
lambda a, b: a + b,
'subtract <a> and <b>':
lambda a, b: a - b,
'<a> (minus|take) <b>':
lambda a, b: a - b,
'<a> squared':
lambda a: a**2,
'<a> cubed':
lambda a: a**3,
'<a> raised to the power <b>':
lambda a, b: a**b,
}把lambda想成"make_function“
def plus(a, b):
return a + b
is the same as
plus = lambda a, b: a + b此外,您还可以使用实际的操作员:例如。*代替operator.mul +而不是add
与任何数字相匹配。8,8.8,-3.14 https://stackoverflow.com/questions/15814592/how-do-i-include-negative-decimal-numbers-in-this-regular-expression这被定义为全局常量
NUM_RE = "-?\d+(\.\d+)?"匹配这个数字,并给它一个可以稍后通过m.groupdict()访问的名称
def named_number_regex(name):
return "(?P<{name}>{num})".format(name=name, num=NUM_RE)
variable_names = ['a', 'b']
for name in variable_names:
# replace all of the name placeholders with
# the actual regex for matching a named number
# eg. "<a>" ---> "(?P<a>-?\d+(\.\d+)?)"
# placeholder were used just to make the above patterns easier to read
old = '<{}>'.format(name)
new = named_number_regex(name)
operations = {k.replace(old, new): v for k, v in operations.items()}
# allow for varying amount of whitespace
operations = {'\s*' + k.replace(' ', '\s*'): v for k, v in operations.items()}现在的模式如下:
#
# \s*(?P<a>-?\d+(\.\d+)?)\s*squared
#
# let's break it down:
#
# \s* ignore leading whitespace
# (?P<a>-?\d+(\.\d+)?) match any number, name it 'a'
# \s* ignore other whitespace
# squared only match if you find " squared"函数来获取字符串,并递归地将其简化,直到得到一个数字或遇到错误为止。
def simplify(inputstring):
print(inputstring) # see what is going on internally
# if you get down to a single number return its value
if re.fullmatch(NUM_RE, inputstring) is not None:
return Decimal(inputstring)
for matcher, oper in operations.items():
# iterate over all key: value pairs in the dict "operations" eg:
# matcher = '(?P<a>\d+) (times|multiplied by) (?P<b>\d+)'
# oper = lambda a, b: operator.mul(a, b)
m = re.match(matcher, inputstring)
if m is None:
continue
# dict of named matches eg {'a': '4', 'b': '8'}
numbers = m.groupdict()
# convert text eg. '4' strings into integers eg. 4
# this is like your [int(d) for d in re.findall(r'-?\d+', inputs)]
# Decimal handles ints and floats, with floating point rounding errors
numbers = {k:Decimal(v) for k, v in numbers.items()}
# now numbers = {'a': 4, 'b': 8}
# get the result of the matched operation
# Note: ** means call function with keyword args from a dict
# eg. oper(a=4, b=8)
result = oper(**numbers)
# substitute the result of oper with the matched string
# Note we can lose precision here when casting Decimal to str
simplified = re.sub(matcher, str(result), inputstring)
# now simplify it further if possible
# this is call recursion, it will continue to simplify until we get down to just a number
print('= ', sep='', end='')
return simplify(simplified)
raise ValueError("Cannot match an operator to \"{}\"".format(inputstring))def test_a_few_cases():
print("\nSimple Addition:")
result = simplify("4 plus 8")
print("\nDemonstrate the recursion:")
result = simplify("2 squared squared squared squared")
print("\nMore elaborate:")
result2 = simplify("2 plus 1.11 times -7 raised to the power 6")
print("\nDemonstrate an Error:")
result = simplify("2 squared squared squared squard")
def main():
print("\nYour input:")
yourresult = simplify(input(">").lower())
if __name__ == '__main__':
test_a_few_cases()
main()https://codereview.stackexchange.com/questions/182551
复制相似问题