简体   繁体   English

为计算器编写计算功能的Pythonic方法-Python

[英]Pythonic way to write calculate function for a calculator - Python

I am creating a text calculator that does not work completely conventionally. 我正在创建一个文本计算器,它不能完全按常规方式工作。 It works like this: 它是这样的:

  • Operation Input: The user inputs the operation the calculator will process ( + for addition, - for subtraction, * for multiplication, or / for division) 操作输入:用户输入计算器将处理的操作( +用于加法, -用于减法, *用于乘法,或/用于除法)
  • Operand Input: The user inputs in each operand of the calculation, pressing Return between operands. 操作数输入:用户在计算的每个操作数中输入,在操作数之间按Return键。 Once the user has inputted all of his desired operands, striking Return three times initiates calculation. 用户输入了所有期望的操作数后,按三次“返回”将启动计算。

Calculation: 计算方式:

When a user enters in more than two operands , instead of doing: 当用户输入两个以上的操作数时 ,而不是这样做:

operand1 plus/minus/times/divided by operand2 , operand1 plus/minus/times/divided by operand2

It does: 它确实:

operand1 plus/minus/times/divided by operand2 plus/minus/times/divided by operand3 , operand1 plus/minus/times/divided by operand2 plus/minus/times/divided by operand3

And so on for all of the inputted operands. 对于所有输入的操作数,依此类推。

The code for this simply loops through the list of inputted operands, operandList , and uses the chosen operation, operation (and result is the result of the calculation): 用于此的代码仅循环遍历输入操作数的列表operandList ,并使用所选的操作, operationresult是计算的结果):

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()

This is super inefficient because it checks for the operation twice, and once inside the while loop, which is even worse. 这是超级低效的,因为它两次检查操作,而一次在while循环中进行检查,这甚至更糟。

Obviously if I write one of those while loop blocks for each operation and begin each one with an if statement to check for the operation that is much worse. 显然,如果我为每个操作编写了while循环块之一,并以if语句开始每个循环,以检查更糟糕的操作。

If I did that you would see that the only difference between each block of code is the operation sign in result +,-,*,/= operandList[operateCount] . 如果我这样做了,您会发现每个代码块之间的唯一区别是result +,-,*,/= operandList[operateCount]

How can I: 我怎样才能:

  • Cut out the redundant code that checks for the operation and executes the respective loop, and 切掉用于检查操作并执行相应循环的冗余代码,以及
  • Reduce/ change the redundant code that checks for the operation when it displays the result ? 减少/更改显示result时检查操作的冗余代码?

Any help is greatly appreciated. 任何帮助是极大的赞赏。 Please ask for specifications if necessary. 请根据需要索取规格。 And if you down vote, please comment your reason for doing so so I can make changes. 如果您投了反对票,请评论您这样做的理由,以便我进行更改。

The key idea is, build a dict : 关键思想是构建一个dict

import operator

ops = {
    '+': (operator.add, 'Sum', 0),
    '-': (operator.sub, 'Difference', 0),
    '*': (operator.mul, 'Product', 1),
    '/': (operator.truediv, 'Quotient', 1),
}

I'm associating to each operator symbols three items: the function to use, the name to use, and (which you seem to have ignored!) the "neutral" starting point. 我将与每个运算符相关的三个项目相关联:要使用的功能,要使用的名称 (中性的)起点(您似乎已经忽略了!)。 Starting always at 0 as you do makes products and quotient risible -- multiply and divide by whatever, it doesn't matter, if it starts at 0 , it stays at 0 forever, you know!-) 总是从0开始,这样就使乘积和商变得更容易-除以任何乘积都没关系,如果它从0开始,就永远保持0

Now things get simpler...: 现在事情变得更简单了:

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()

I have no idea why you're so inordinately fond of global and messing with indexing without necessity. 知道为什么您如此狂热地喜欢global并且不必要地使用索引。 is_number apparently is a method only of float s and you're initializing result to an int , so it could crash the code -- I've replaced it with a sensible check. is_number显然仅是float的一种方法,并且您正在将result初始化为int ,因此它可能使代码崩溃—我已将其替换为明智的检查。

No need for global for names you're only using and not assigning -- and of course it would make sense to lose the global result and instead return result at the end; 您只需要使用而不是分配的global名称就不需要了-当然,丢失global result并在最后return result是有意义的; but I've left it in just in case there might be any sane reason to have it global (I can't think of any). 但我留给它的目的是,以防万一有任何理智的理由将它全局化(我想不到)。

But the core idea is: in Python, for dispatching purposes, think dict first and foremost! 但是核心思想是:在Python中,出于调度目的,首先要考虑dict

Added: OP asks peculiar questions in comments, such as "What exactly is the function of the import statement?" 补充:OP在注释中提出了一些特殊的问题,例如“ import语句的功能到底是什么?” -- answer, obviously, is "to make another module available" (in this case, module operator from Python's standard library, to get its functions performing addition, multiplication, and so forth). -显然,答案是“使另一个模块可用”(在这种情况下,是Python标准库中的模块operator ,以使其功能执行加,乘等操作)。 Also "what is the 'neutral starting point'" -- answer, obviously, is "the initial value of result before you start adding, multiplying and so on. 另外,“什么是'中性起点'”-显然,答案是“开始加,乘等等之前result的初始值。

In the OP's original code in the Q, result was unconditionally initialized to zero. 在OP的原始代码Q中, result被无条件初始化为零。 If you start with zero and multiply it by whatever number(s), it stays zero -- it's not a "neutral" starting point for a series of multiplication, it's more of a "fixed" point, a "black hole" in a sense. 如果您从零开始并乘以任何数字,它将保持为零-这不是一系列乘法的“中立”起点,它更像是“固定”点,即“黑洞”。感。 So, I used different initial values depending on the operation. 因此,我根据操作使用了不同的初始值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM