Python为计算器编写计算函数的 ic 方法 - Python
Pythonic way to write calculate function for a calculator - Python
我正在创建一个不能完全按常规工作的文本计算器。它是这样工作的:
- 运算输入:用户输入计算器将要处理的运算(
+
为加法,-
为减法,*
为乘法,或 /
除法)
- 操作数输入: 用户在计算的每个操作数中输入,在操作数之间按Return。一旦用户输入了所有他想要的操作数,点击Return三次开始计算。
计算:
当用户输入 两个以上的操作数 时,而不是:
operand1 plus/minus/times/divided by operand2
,
确实如此:
operand1 plus/minus/times/divided by operand2 plus/minus/times/divided by operand3
,
所有输入的操作数依此类推。
此代码简单地循环遍历输入的操作数列表 operandList
,并使用所选操作 operation
(result
是计算结果):
def Calculate():
global operation, operandList, result
operateCount = 0
result = 0
while operateCount < len(operandList):
if operation == '+':
result += operandList[operateCount]
elif operation == '-':
result -= operandList[operateCount]
elif operation == '*':
result *= operandList[operateCount]
elif operation == '/':
result /= operandList[operateCount]
operateCount += 1
if operation == '+':
resultName = 'Sum'
elif operation == '-':
resultName = 'Difference'
elif operation == '*':
resultName = 'Product'
elif operation == '/':
resultName = 'Quotient'
if result.is_integer():
print(int(result), '=', resultName)
else:
print(result, '=', resultName)
print()
这是非常低效的,因为它检查操作两次,一次在 while 循环中,这更糟糕。
显然,如果我为每个操作编写一个 while 循环块,并以 if 语句开始每个块以检查更糟糕的操作。
如果我那样做了,您会发现每个代码块之间的唯一区别是 result +,-,*,/= operandList[operateCount]
中的操作符号。
我怎样才能:
- 删除检查操作和执行相应循环的冗余代码,
- 减少/更改显示
result
? 时检查操作的冗余代码
非常感谢任何帮助。如有需要,请索取规格。如果您投反对票,请评论您这样做的原因,以便我做出更改。
关键思想是,构建一个 dict
:
import operator
ops = {
'+': (operator.add, 'Sum', 0),
'-': (operator.sub, 'Difference', 0),
'*': (operator.mul, 'Product', 1),
'/': (operator.truediv, 'Quotient', 1),
}
我将每个运算符符号三个项目关联起来:要使用的函数,要使用的名称,和(你似乎忽略了!) "neutral" 起点。总是从 0
开始,就像你所做的那样,乘积和商可以笑——乘以和除以任何东西,没关系,如果它从 0
开始,它 保持 永远在0
,你知道!-)
现在事情变得简单了...:[=28=]
def Calculate():
global result
op, resultName, result = ops[operation]
for item in operandList:
result = op(result, item)
if result == int(result):
print(int(result), '=', resultName)
else:
print(result, '=', resultName)
print()
我 不 知道为什么你如此偏爱 global
并且在没有必要的情况下搞乱索引。 is_number
显然只是 float
的方法,并且您正在将 result
初始化为 int
,因此它可能会使代码崩溃——我已将其替换为明智的检查。
不需要 global
用于您仅使用的名称并且 不 分配 - 当然丢失 global result
是有意义的而不是 return result
最后;但我把它留了下来,以防万一有任何理智的理由让它成为全球性的(我想不出任何理由)。
但核心思想是:在Python中,出于调度目的,首先考虑dict
!
添加:OP 在评论中提出特殊问题,例如 "What exactly is the function of the import statement?"——答案显然是 "to make another module available"(在这种情况下,来自 Python 的模块 operator
的标准库,以获取其执行加法、乘法等的函数)。另外 "what is the 'neutral starting point'" -- 显然,答案是“开始加法、乘法等之前 result
的初始值。
OP在Q中的原始代码中,result
被无条件初始化为零。如果您从零开始并将它乘以任何数字,它 保持 零——它不是一系列乘法的 "neutral" 起点,它更像是一个"fixed"点,某种意义上的"black hole"。所以,我根据操作使用了不同的初始值。
我正在创建一个不能完全按常规工作的文本计算器。它是这样工作的:
- 运算输入:用户输入计算器将要处理的运算(
+
为加法,-
为减法,*
为乘法,或/
除法) - 操作数输入: 用户在计算的每个操作数中输入,在操作数之间按Return。一旦用户输入了所有他想要的操作数,点击Return三次开始计算。
计算:
当用户输入 两个以上的操作数 时,而不是:
operand1 plus/minus/times/divided by operand2
,
确实如此:
operand1 plus/minus/times/divided by operand2 plus/minus/times/divided by operand3
,
所有输入的操作数依此类推。
此代码简单地循环遍历输入的操作数列表 operandList
,并使用所选操作 operation
(result
是计算结果):
def Calculate():
global operation, operandList, result
operateCount = 0
result = 0
while operateCount < len(operandList):
if operation == '+':
result += operandList[operateCount]
elif operation == '-':
result -= operandList[operateCount]
elif operation == '*':
result *= operandList[operateCount]
elif operation == '/':
result /= operandList[operateCount]
operateCount += 1
if operation == '+':
resultName = 'Sum'
elif operation == '-':
resultName = 'Difference'
elif operation == '*':
resultName = 'Product'
elif operation == '/':
resultName = 'Quotient'
if result.is_integer():
print(int(result), '=', resultName)
else:
print(result, '=', resultName)
print()
这是非常低效的,因为它检查操作两次,一次在 while 循环中,这更糟糕。
显然,如果我为每个操作编写一个 while 循环块,并以 if 语句开始每个块以检查更糟糕的操作。
如果我那样做了,您会发现每个代码块之间的唯一区别是 result +,-,*,/= operandList[operateCount]
中的操作符号。
我怎样才能:
- 删除检查操作和执行相应循环的冗余代码,
- 减少/更改显示
result
? 时检查操作的冗余代码
非常感谢任何帮助。如有需要,请索取规格。如果您投反对票,请评论您这样做的原因,以便我做出更改。
关键思想是,构建一个 dict
:
import operator
ops = {
'+': (operator.add, 'Sum', 0),
'-': (operator.sub, 'Difference', 0),
'*': (operator.mul, 'Product', 1),
'/': (operator.truediv, 'Quotient', 1),
}
我将每个运算符符号三个项目关联起来:要使用的函数,要使用的名称,和(你似乎忽略了!) "neutral" 起点。总是从 0
开始,就像你所做的那样,乘积和商可以笑——乘以和除以任何东西,没关系,如果它从 0
开始,它 保持 永远在0
,你知道!-)
现在事情变得简单了...:[=28=]
def Calculate():
global result
op, resultName, result = ops[operation]
for item in operandList:
result = op(result, item)
if result == int(result):
print(int(result), '=', resultName)
else:
print(result, '=', resultName)
print()
我 不 知道为什么你如此偏爱 global
并且在没有必要的情况下搞乱索引。 is_number
显然只是 float
的方法,并且您正在将 result
初始化为 int
,因此它可能会使代码崩溃——我已将其替换为明智的检查。
不需要 global
用于您仅使用的名称并且 不 分配 - 当然丢失 global result
是有意义的而不是 return result
最后;但我把它留了下来,以防万一有任何理智的理由让它成为全球性的(我想不出任何理由)。
但核心思想是:在Python中,出于调度目的,首先考虑dict
!
添加:OP 在评论中提出特殊问题,例如 "What exactly is the function of the import statement?"——答案显然是 "to make another module available"(在这种情况下,来自 Python 的模块 operator
的标准库,以获取其执行加法、乘法等的函数)。另外 "what is the 'neutral starting point'" -- 显然,答案是“开始加法、乘法等之前 result
的初始值。
OP在Q中的原始代码中,result
被无条件初始化为零。如果您从零开始并将它乘以任何数字,它 保持 零——它不是一系列乘法的 "neutral" 起点,它更像是一个"fixed"点,某种意义上的"black hole"。所以,我根据操作使用了不同的初始值。