首页 > 解决方案 > 如何在 Python 中压缩这个 if 语句?

问题描述

我目前正在用 Python 创建一个计算器,但遇到了一个小问题:我的 if-else 语句中有 28 个条件:

if operation0 == "+" and operation1 == "+" and operation2 == "+": # First operation is addition
    print(number0 + number1 + number2 + number3)
elif operation0 == "+" and operation1 == "+" and operation2 == "*":
    print(number0 + number1 + number2 * number3)
elif operation0 == "+" and operation1 == "+" and operation2 == "^":
    print(number0 + number1 + number2 ** number3)
elif operation0 == "+" and operation1 == "*" and operation2 == "+":
    print(number0 + number1 * number2 + number3)
elif operation0 == "+" and operation1 == "*" and operation2 == "*":
    print(number0 + number1 * number2 * number3)
elif operation0 == "+" and operation1 == "*" and operation2 == "^":
    print(number0 + number1 * number2 ** number3)
elif operation0 == "+" and operation1 == "^" and operation2 == "+":
    print(number0 + number1 ** number2 + number3)
elif operation0 == "+" and operation1 == "^" and operation2 == "*":
    print(number0 + number1 ** number2 * number3)
elif operation0 == "+" and operation1 == "^" and operation2 == "^":
    print(number0 + number1 ** number2 ** number3)
elif operation0 == "*" and operation1 == "+" and operation2 == "+": # First operation is multiplication
    print(number0 * number1 + number2 + number3)
elif operation0 == "*" and operation1 == "+" and operation2 == "*":
    print(number0 * number1 + number2 * number3)
elif operation0 == "*" and operation1 == "+" and operation2 == "^":
    print(number0 * number1 + number2 ** number3)
elif operation0 == "*" and operation1 == "*" and operation2 == "+":
    print(number0 * number1 * number2 + number3)
elif operation0 == "*" and operation1 == "*" and operation2 == "*":
    print(number0 * number1 * number2 * number3)
elif operation0 == "*" and operation1 == "*" and operation2 == "^":
    print(number0 * number1 * number2 ** number3)
elif operation0 == "*" and operation1 == "^" and operation2 == "+":
    print(number0 * number1 ** number2 + number3)
elif operation0 == "*" and operation1 == "^" and operation2 == "*":
    print(number0 * number1 ** number2 * number3)
elif operation0 == "*" and operation1 == "^" and operation2 == "^":
    print(number0 * number1 ** number2 ** number3)
elif operation0 == "^" and operation1 == "+" and operation2 == "+": # First operation is exponentiation
    print(number0 ** number1 + number2 + number3)
elif operation0 == "^" and operation1 == "+" and operation2 == "*":
    print(number0 ** number1 + number2 * number3)
elif operation0 == "^" and operation1 == "+" and operation2 == "^":
    print(number0 ** number1 + number2 ** number3)
elif operation0 == "^" and operation1 == "*" and operation2 == "+":
    print(number0 ** number1 * number2 + number3)
elif operation0 == "^" and operation1 == "*" and operation2 == "*":
    print(number0 ** number1 * number2 * number3)
elif operation0 == "^" and operation1 == "*" and operation2 == "^":
    print(number0 ** number1 * number2 ** number3)
elif operation0 == "^" and operation1 == "^" and operation2 == "+":
    print(number0 ** number1 ** number2 + number3)
elif operation0 == "^" and operation1 == "^" and operation2 == "*":
    print(number0 ** number1 ** number2 * number3)
elif operation0 == "^" and operation1 == "^" and operation2 == "^":
    print(number0 ** number1 ** number2 ** number3)
else:
    print("Error")

我尝试过的没有任何效果,我在这个网站上找不到任何可以帮助我压缩代码的东西。这么多重复的 elif 是不合理的,任何数量的减少都将不胜感激。

标签: pythonif-statement

解决方案


免责声明:该解决方案可能会使用各种概念,这些概念在此处无法解释。

要获得优先权,您必须正确解析输入。有几种方法可以做到这一点;一种常见的方法是 Dijkstra 的调车场算法。
由于这只是一个示例,我们将放弃良好实践(错误处理、类)以获得更简洁的代码。

首先,我们需要列出优先级。更高的优先级意味着运算符具有更高的优先级,因此它会更早地执行。

precedences = {
    '^': 3,
    '*': 2, '/': 2,
    '+': 1, '-': 1
}

然后,我们需要将操作与每个操作员相关联。为此,我们可以使用operator模块中的函数:

from operator import pow, truediv, mul, add, sub
do = {
    '^': pow,
    '*': mul, '/': truediv,
    '+': add, '-': sub
}

最后,我们需要实现决定何时评估表达式的逻辑。首先,我们比操作多一个数字,所以我们把它放到堆栈中:

def shunt(numbers, operations):
    stack = [numbers.pop(0)]
    operators = []

然后,我们处理每个运算符号对。

    while len(numbers):
        operator = operations.pop(0)
        precedence = precedences[operator]

do当一个操作具有比当前操作更高的优先级(执行得更早)时,它会被评估(使用字典)。我们从堆栈中删除左右操作数,并从中查找适当的函数do以评估结果:

        while operators and precedences[operators[-1]] >= precedence:
            [left, right], stack[-2:] = stack[-2:], []
            stack.append(do[operators.pop()](left, right))

然后我们将当前运算符和数字附加到堆栈中:

        operators.append(operator)
        stack.append(numbers.pop(0))

在所有数字和运算符都用完后,我们评估其余的运算符,直到只剩下一个数字,然后返回:

    while len(stack) > 1:
        [left, right], stack[-2:] = stack[-2:], []
        stack.append(do[operators.pop()](left, right))
    return stack[0]

将它们放在一起(在线尝试!):

from operator import pow, truediv, mul, add, sub

precedences = {
    '^': 3,
    '*': 2, '/': 2,
    '+': 1, '-': 1
}

do = {
    '^': pow,
    '*': mul, '/': truediv,
    '+': add, '-': sub
}

def shunt(numbers, operations):
    stack = [numbers.pop(0)]
    operators = []
    while len(numbers):
        operator = operations.pop(0)
        precedence = precedences[operator]
        while operators and precedences[operators[-1]] >= precedence:
            [left, right], stack[-2:] = stack[-2:], []
            stack.append(do[operators.pop()](left, right))
        operators.append(operator)
        stack.append(numbers.pop(0))
    while len(stack) > 1:
        [left, right], stack[-2:] = stack[-2:], []
        stack.append(do[operators.pop()](left, right))
    return stack[0]

推荐阅读